mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-11 19:58:22 +00:00
Merge branch 'FF/Develop' into FF/Fox2
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -291,17 +291,34 @@ do -- DETECTION_BASE
|
||||
--- @type DETECTION_BASE.DetectedItems
|
||||
-- @list <#DETECTION_BASE.DetectedItem>
|
||||
|
||||
--- @type DETECTION_BASE.DetectedItem
|
||||
--- Detected item data structrue.
|
||||
-- @type DETECTION_BASE.DetectedItem
|
||||
-- @field #boolean IsDetected Indicates if the DetectedItem has been detected or not.
|
||||
-- @field Core.Set#SET_UNIT Set
|
||||
-- @field Core.Set#SET_UNIT Set -- The Set of Units in the detected area.
|
||||
-- @field Core.Zone#ZONE_UNIT Zone -- The Zone of the detected area.
|
||||
-- @field #boolean Changed Documents if the detected area has changes.
|
||||
-- @field Core.Set#SET_UNIT Set The Set of Units in the detected area.
|
||||
-- @field Core.Zone#ZONE_UNIT Zone The Zone of the detected area.
|
||||
-- @field #boolean Changed Documents if the detected area has changed.
|
||||
-- @field #table Changes A list of the changes reported on the detected area. (It is up to the user of the detected area to consume those changes).
|
||||
-- @field #number ID -- The identifier of the detected area.
|
||||
-- @field #number ID The identifier of the detected area.
|
||||
-- @field #boolean FriendliesNearBy Indicates if there are friendlies within the detected area.
|
||||
-- @field Wrapper.Unit#UNIT NearestFAC The nearest FAC near the Area.
|
||||
-- @field Core.Point#COORDINATE Coordinate The last known coordinate of the DetectedItem.
|
||||
-- @field Core.Point#COORDINATE InterceptCoord Intercept coordiante.
|
||||
-- @field #number DistanceRecce Distance in meters of the Recce.
|
||||
-- @field #number Index Detected item key. Could also be a string.
|
||||
-- @field #string ItemID ItemPrefix .. "." .. self.DetectedItemMax.
|
||||
-- @field #boolean Locked Lock detected item.
|
||||
-- @field #table PlayersNearBy Table of nearby players.
|
||||
-- @field #table FriendliesDistance Table of distances to friendly units.
|
||||
-- @field #string TypeName Type name of the detected unit.
|
||||
-- @field #string CategoryName Catetory name of the detected unit.
|
||||
-- @field #string Name Name of the detected object.
|
||||
-- @field #boolean IsVisible If true, detected object is visible.
|
||||
-- @field #number LastTime Last time the detected item was seen.
|
||||
-- @field DCS#Vec3 LastPos Last known position of the detected item.
|
||||
-- @field DCS#Vec3 LastVelocity Last recorded 3D velocity vector of the detected item.
|
||||
-- @field #boolean KnowType Type of detected item is known.
|
||||
-- @field #boolean KnowDistance Distance to the detected item is known.
|
||||
-- @field #number Distance Distance to the detected item.
|
||||
|
||||
--- DETECTION constructor.
|
||||
-- @param #DETECTION_BASE self
|
||||
@@ -441,15 +458,18 @@ do -- DETECTION_BASE
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @param #table Units Table of detected units.
|
||||
|
||||
--- Synchronous Event Trigger for Event Detected.
|
||||
-- @function [parent=#DETECTION_BASE] Detected
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #table Units Table of detected units.
|
||||
|
||||
--- Asynchronous Event Trigger for Event Detected.
|
||||
-- @function [parent=#DETECTION_BASE] __Detected
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
-- @param #table Units Table of detected units.
|
||||
|
||||
self:AddTransition( "Detecting", "DetectedItem", "Detecting" )
|
||||
|
||||
@@ -569,7 +589,7 @@ do -- DETECTION_BASE
|
||||
|
||||
local HasDetectedObjects = false
|
||||
|
||||
if Detection:IsAlive() then
|
||||
if Detection and Detection:IsAlive() then
|
||||
|
||||
--self:T( { "DetectionGroup is Alive", DetectionGroup:GetName() } )
|
||||
|
||||
@@ -800,12 +820,17 @@ do -- DETECTION_BASE
|
||||
end
|
||||
|
||||
self:CreateDetectionItems() -- Polymorphic call to Create/Update the DetectionItems list for the DETECTION_ class grouping method.
|
||||
|
||||
for DetectedItemID, DetectedItem in pairs( self.DetectedItems ) do
|
||||
|
||||
self:UpdateDetectedItemDetection( DetectedItem )
|
||||
|
||||
self:CleanDetectionItem( DetectedItem, DetectedItemID ) -- Any DetectionItem that has a Set with zero elements in it, must be removed from the DetectionItems list.
|
||||
|
||||
if DetectedItem then
|
||||
self:__DetectedItem( 0.1, DetectedItem )
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -817,7 +842,7 @@ do -- DETECTION_BASE
|
||||
|
||||
do -- DetectionItems Creation
|
||||
|
||||
-- Clean the DetectedItem table.
|
||||
--- Clean the DetectedItem table.
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @return #DETECTION_BASE
|
||||
function DETECTION_BASE:CleanDetectionItem( DetectedItem, DetectedItemID )
|
||||
@@ -1234,7 +1259,7 @@ do -- DETECTION_BASE
|
||||
|
||||
--- Returns if there are friendlies nearby the FAC units ...
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param DetectedItem
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @param DCS#Unit.Category Category The category of the unit.
|
||||
-- @return #boolean true if there are friendlies nearby
|
||||
function DETECTION_BASE:IsFriendliesNearBy( DetectedItem, Category )
|
||||
@@ -1244,7 +1269,7 @@ do -- DETECTION_BASE
|
||||
|
||||
--- Returns friendly units nearby the FAC units ...
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param DetectedItem
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @param DCS#Unit.Category Category The category of the unit.
|
||||
-- @return #map<#string,Wrapper.Unit#UNIT> The map of Friendly UNITs.
|
||||
function DETECTION_BASE:GetFriendliesNearBy( DetectedItem, Category )
|
||||
@@ -1254,6 +1279,7 @@ do -- DETECTION_BASE
|
||||
|
||||
--- Returns if there are friendlies nearby the intercept ...
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @return #boolean trhe if there are friendlies near the intercept.
|
||||
function DETECTION_BASE:IsFriendliesNearIntercept( DetectedItem )
|
||||
|
||||
@@ -1262,6 +1288,7 @@ do -- DETECTION_BASE
|
||||
|
||||
--- Returns friendly units nearby the intercept point ...
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem The detected item.
|
||||
-- @return #map<#string,Wrapper.Unit#UNIT> The map of Friendly UNITs.
|
||||
function DETECTION_BASE:GetFriendliesNearIntercept( DetectedItem )
|
||||
|
||||
@@ -1270,7 +1297,8 @@ do -- DETECTION_BASE
|
||||
|
||||
--- Returns the distance used to identify friendlies near the deteted item ...
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @return #number The distance.
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem The detected item.
|
||||
-- @return #table A table of distances to friendlies.
|
||||
function DETECTION_BASE:GetFriendliesDistance( DetectedItem )
|
||||
|
||||
return DetectedItem.FriendliesDistance
|
||||
@@ -1278,6 +1306,7 @@ do -- DETECTION_BASE
|
||||
|
||||
--- Returns if there are friendlies nearby the FAC units ...
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @return #boolean trhe if there are friendlies nearby
|
||||
function DETECTION_BASE:IsPlayersNearBy( DetectedItem )
|
||||
|
||||
@@ -1286,6 +1315,7 @@ do -- DETECTION_BASE
|
||||
|
||||
--- Returns friendly units nearby the FAC units ...
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem The detected item.
|
||||
-- @return #map<#string,Wrapper.Unit#UNIT> The map of Friendly UNITs.
|
||||
function DETECTION_BASE:GetPlayersNearBy( DetectedItem )
|
||||
|
||||
@@ -1294,10 +1324,11 @@ do -- DETECTION_BASE
|
||||
|
||||
--- Background worker function to determine if there are friendlies nearby ...
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #table TargetData
|
||||
function DETECTION_BASE:ReportFriendliesNearBy( TargetData )
|
||||
--self:F( { "Search Friendlies", DetectedItem = TargetData.DetectedItem } )
|
||||
|
||||
local DetectedItem = TargetData.DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
|
||||
local DetectedItem = TargetData.DetectedItem --#DETECTION_BASE.DetectedItem
|
||||
local DetectedSet = TargetData.DetectedItem.Set
|
||||
local DetectedUnit = DetectedSet:GetFirst() -- Wrapper.Unit#UNIT
|
||||
|
||||
@@ -1519,13 +1550,13 @@ do -- DETECTION_BASE
|
||||
--- Adds a new DetectedItem to the DetectedItems list.
|
||||
-- The DetectedItem is a table and contains a SET_UNIT in the field Set.
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param ItemPrefix
|
||||
-- @param DetectedItemKey The key of the DetectedItem.
|
||||
-- @param #string ItemPrefix Prefix of detected item.
|
||||
-- @param #number DetectedItemKey The key of the DetectedItem. Default self.DetectedItemMax. Could also be a string in principle.
|
||||
-- @param Core.Set#SET_UNIT Set (optional) The Set of Units to be added.
|
||||
-- @return #DETECTION_BASE.DetectedItem
|
||||
function DETECTION_BASE:AddDetectedItem( ItemPrefix, DetectedItemKey, Set )
|
||||
|
||||
local DetectedItem = {}
|
||||
local DetectedItem = {} --#DETECTION_BASE.DetectedItem
|
||||
self.DetectedItemCount = self.DetectedItemCount + 1
|
||||
self.DetectedItemMax = self.DetectedItemMax + 1
|
||||
|
||||
@@ -1706,6 +1737,7 @@ do -- DETECTION_BASE
|
||||
|
||||
--- Checks if there is at least one UNIT detected in the Set of the the DetectedItem.
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @return #boolean true if at least one UNIT is detected from the DetectedSet, false if no UNIT was detected from the DetectedSet.
|
||||
function DETECTION_BASE:IsDetectedItemDetected( DetectedItem )
|
||||
|
||||
@@ -1832,8 +1864,7 @@ do -- DETECTION_BASE
|
||||
|
||||
--- Get a list of the detected item coordinates.
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem The DetectedItem to set the coordinate at.
|
||||
-- @return Core.Point#COORDINATE
|
||||
-- @return #table A table of Core.Point#COORDINATE
|
||||
function DETECTION_BASE:GetDetectedItemCoordinates()
|
||||
|
||||
local Coordinates = {}
|
||||
@@ -1898,7 +1929,7 @@ do -- DETECTION_BASE
|
||||
|
||||
--- Get the Detection Set.
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @return Core.Set#SET_BASE
|
||||
-- @return #DETECTION_BASE self
|
||||
function DETECTION_BASE:GetDetectionSet()
|
||||
|
||||
local DetectionSet = self.DetectionSet
|
||||
@@ -2033,7 +2064,8 @@ do -- DETECTION_UNITS
|
||||
function DETECTION_UNITS:CreateDetectionItems()
|
||||
-- Loop the current detected items, and check if each object still exists and is detected.
|
||||
|
||||
for DetectedItemKey, DetectedItem in pairs( self.DetectedItems ) do
|
||||
for DetectedItemKey, _DetectedItem in pairs( self.DetectedItems ) do
|
||||
local DetectedItem=_DetectedItem --#DETECTION_BASE.DetectedItem
|
||||
|
||||
local DetectedItemSet = DetectedItem.Set -- Core.Set#SET_UNIT
|
||||
|
||||
|
||||
@@ -40,7 +40,9 @@
|
||||
-- @field #table launchzones Table of launch zones.
|
||||
-- @field Core.Set#SET_GROUP protectedset Set of protected groups.
|
||||
-- @field #number explosionpower Power of explostion when destroying the missile in kg TNT. Default 5 kg TNT.
|
||||
-- @field #number explosiondist Missile player distance in meters for destroying the missile. Default 100 m.
|
||||
-- @field #number explosiondist Missile player distance in meters for destroying smaller missiles. Default 200 m.
|
||||
-- @field #number explosiondist2 Missile player distance in meters for destroying big missiles. Default 500 m.
|
||||
-- @field #number bigmissilemass Explosion power of big missiles. Default 50 kg TNT. Big missiles will be destroyed earlier.
|
||||
-- @field #number dt50 Time step [sec] for missile position updates if distance to target > 50 km. Default 5 sec.
|
||||
-- @field #number dt10 Time step [sec] for missile position updates if distance to target > 10 km and < 50 km. Default 1 sec.
|
||||
-- @field #number dt05 Time step [sec] for missile position updates if distance to target > 5 km and < 10 km. Default 0.5 sec.
|
||||
@@ -136,8 +138,10 @@ FOX = {
|
||||
safezones = {},
|
||||
launchzones = {},
|
||||
protectedset = nil,
|
||||
explosionpower = 5,
|
||||
explosiondist = 100,
|
||||
explosionpower = 0.1,
|
||||
explosiondist = 200,
|
||||
explosiondist2 = 500,
|
||||
bigmissilemass = 50,
|
||||
destroy = nil,
|
||||
dt50 = 5,
|
||||
dt10 = 1,
|
||||
@@ -169,14 +173,19 @@ FOX = {
|
||||
-- @field Wrapper.Unit#UNIT weapon Missile weapon unit.
|
||||
-- @field #boolean active If true the missile is active.
|
||||
-- @field #string missileType Type of missile.
|
||||
-- @field #string missileName Name of missile.
|
||||
-- @field #number missileRange Range of missile in meters.
|
||||
-- @field #number fuseDist Fuse distance in meters.
|
||||
-- @field #number explosive Explosive mass in kg TNT.
|
||||
-- @field Wrapper.Unit#UNIT shooterUnit Unit that shot the missile.
|
||||
-- @field Wrapper.Group#GROUP shooterGroup Group that shot the missile.
|
||||
-- @field #number shooterCoalition Coalition side of the shooter.
|
||||
-- @field #string shooterName Name of the shooter unit.
|
||||
-- @field #number shotTime Abs mission time in seconds the missile was fired.
|
||||
-- @field #number shotTime Abs. mission time in seconds the missile was fired.
|
||||
-- @field Core.Point#COORDINATE shotCoord Coordinate where the missile was fired.
|
||||
-- @field Wrapper.Unit#UNIT targetUnit Unit that was targeted.
|
||||
-- @field #string targetName Name of the target unit or "unknown".
|
||||
-- @field #string targetOrig Name of the "original" target, i.e. the one right after launched.
|
||||
-- @field #FOX.PlayerData targetPlayer Player that was targeted or nil.
|
||||
|
||||
--- Main radio menu on group level.
|
||||
@@ -189,7 +198,7 @@ FOX.MenuF10Root=nil
|
||||
|
||||
--- FOX class version.
|
||||
-- @field #string version
|
||||
FOX.version="0.5.1"
|
||||
FOX.version="0.6.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
@@ -217,6 +226,10 @@ function FOX:New()
|
||||
self:SetDefaultMissileDestruction(true)
|
||||
self:SetDefaultLaunchAlerts(true)
|
||||
self:SetDefaultLaunchMarks(true)
|
||||
|
||||
-- Explosion/destruction defaults.
|
||||
self:SetExplosionDistance()
|
||||
self:SetExplosionDistanceBigMissiles()
|
||||
self:SetExplosionPower()
|
||||
|
||||
-- Start State.
|
||||
@@ -358,12 +371,16 @@ function FOX:onafterStart(From, Event, To)
|
||||
self:HandleEvent(EVENTS.Birth)
|
||||
self:HandleEvent(EVENTS.Shot)
|
||||
|
||||
if self.Debug then
|
||||
self:HandleEvent(EVENTS.Hit)
|
||||
end
|
||||
|
||||
if self.Debug then
|
||||
self:TraceClass(self.ClassName)
|
||||
self:TraceLevel(2)
|
||||
end
|
||||
|
||||
self:__Status(-10)
|
||||
self:__Status(-20)
|
||||
end
|
||||
|
||||
--- On after Stop event. Stops the missile trainer and unhandles events.
|
||||
@@ -378,8 +395,12 @@ function FOX:onafterStop(From, Event, To)
|
||||
env.info(text)
|
||||
|
||||
-- Handle events:
|
||||
self:UnhandleEvent(EVENTS.Birth)
|
||||
self:UnhandleEvent(EVENTS.Shot)
|
||||
self:UnHandleEvent(EVENTS.Birth)
|
||||
self:UnHandleEvent(EVENTS.Shot)
|
||||
|
||||
if self.Debug then
|
||||
self:UnhandleEvent(EVENTS.Hit)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -433,28 +454,42 @@ function FOX:AddProtectedGroup(group)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set explosion power.
|
||||
--- Set explosion power. This is an "artificial" explosion generated when the missile is destroyed. Just for the visual effect.
|
||||
-- Don't set the explosion power too big or it will harm the aircraft in the vicinity.
|
||||
-- @param #FOX self
|
||||
-- @param #number power Explosion power in kg TNT. Default 5.
|
||||
-- @param #number power Explosion power in kg TNT. Default 0.1 kg.
|
||||
-- @return #FOX self
|
||||
function FOX:SetExplosionPower(power)
|
||||
|
||||
self.explosionpower=power or 5
|
||||
self.explosionpower=power or 0.1
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set missile-player distance when missile is destroyed.
|
||||
-- @param #FOX self
|
||||
-- @param #number distance Distance in meters. Default 100 m.
|
||||
-- @param #number distance Distance in meters. Default 200 m.
|
||||
-- @return #FOX self
|
||||
function FOX:SetExplosionDistance(distance)
|
||||
|
||||
self.explosiondist=distance or 100
|
||||
self.explosiondist=distance or 200
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set missile-player distance when BIG missiles are destroyed.
|
||||
-- @param #FOX self
|
||||
-- @param #number distance Distance in meters. Default 500 m.
|
||||
-- @param #number explosivemass Explosive mass of missile threshold in kg TNT. Default 50 kg.
|
||||
-- @return #FOX self
|
||||
function FOX:SetExplosionDistanceBigMissiles(distance, explosivemass)
|
||||
|
||||
self.explosiondist2=distance or 500
|
||||
|
||||
self.bigmissilemass=explosivemass or 50
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Disable F10 menu for all players.
|
||||
-- @param #FOX self
|
||||
@@ -558,8 +593,11 @@ function FOX:onafterStatus(From, Event, To)
|
||||
-- Get FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
local time=timer.getAbsTime()
|
||||
local clock=UTILS.SecondsToClock(time)
|
||||
|
||||
-- Status.
|
||||
self:I(self.lid..string.format("Missile trainer status: %s", fsmstate))
|
||||
self:I(self.lid..string.format("Missile trainer status %s: %s", clock, fsmstate))
|
||||
|
||||
-- Check missile status.
|
||||
self:_CheckMissileStatus()
|
||||
@@ -664,6 +702,9 @@ function FOX:_CheckMissileStatus()
|
||||
text=text..string.format("\n[%d] %s: active=%s, range=%.1f NM, heading=%03d, target=%s, player=%s, missilename=%s", i, mtype, active, range, heading, targetname, playername, missile.missileName)
|
||||
|
||||
end
|
||||
if #self.missiles==0 then
|
||||
text=text.." none"
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Remove inactive missiles.
|
||||
@@ -722,7 +763,9 @@ end
|
||||
function FOX:onafterMissileLaunch(From, Event, To, missile)
|
||||
|
||||
-- Tracking info and init of last bomb position.
|
||||
self:I(FOX.lid..string.format("FOX: Tracking %s - %s.", missile.missileType, missile.missileName))
|
||||
local text=string.format("FOX: Tracking missile %s(%s) - target %s - shooter %s", missile.missileType, missile.missileName, tostring(missile.targetName), missile.shooterName)
|
||||
self:I(FOX.lid..text)
|
||||
MESSAGE:New(text, 10):ToAllIf(self.Debug)
|
||||
|
||||
-- Loop over players.
|
||||
for _,_player in pairs(self.players) do
|
||||
@@ -803,6 +846,9 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
||||
-- Missile velocity in m/s.
|
||||
local missileVelocity=UTILS.VecNorm(_ordnance:getVelocity())
|
||||
|
||||
-- Update missile target if necessary.
|
||||
self:GetMissileTarget(missile)
|
||||
|
||||
if missile.targetUnit then
|
||||
|
||||
-----------------------------------
|
||||
@@ -825,7 +871,30 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
||||
|
||||
------------------------------------
|
||||
-- Missile has NO specific target --
|
||||
------------------------------------
|
||||
------------------------------------
|
||||
|
||||
-- TODO: This might cause a problem with wingman. Even if the shooter itself is excluded from the check, it's wingmen are not.
|
||||
-- That would trigger the distance check right after missile launch if things to wrong.
|
||||
--
|
||||
-- Possible solutions:
|
||||
-- * Time check: enable this check after X seconds after missile was fired. What is X?
|
||||
-- * Coalition check. But would not work in training situations where blue on blue is valid!
|
||||
-- * At least enable it for surface-to-air missiles.
|
||||
|
||||
local function _GetTarget(_unit)
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
-- Player position.
|
||||
local playerCoord=unit:GetCoordinate()
|
||||
|
||||
-- Distance.
|
||||
local dist=missileCoord:Get3DDistance(playerCoord)
|
||||
|
||||
-- Update mindist if necessary. Only include players in range of missile + 50% safety margin.
|
||||
if dist<=self.explosiondist then
|
||||
return unit
|
||||
end
|
||||
end
|
||||
|
||||
-- Distance to closest player.
|
||||
local mindist=nil
|
||||
@@ -843,17 +912,57 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
||||
-- Distance.
|
||||
local dist=missileCoord:Get3DDistance(playerCoord)
|
||||
|
||||
-- Maxrange from launch point to player.
|
||||
local maxrange=playerCoord:Get3DDistance(missile.shotCoord)
|
||||
-- Distance from shooter to player.
|
||||
local Dshooter2player=playerCoord:Get3DDistance(missile.shotCoord)
|
||||
|
||||
-- Update mindist if necessary. Only include players in range of missile.
|
||||
if (mindist==nil or dist<mindist) and dist<=maxrange then
|
||||
-- Update mindist if necessary. Only include players in range of missile + 50% safety margin.
|
||||
if (mindist==nil or dist<mindist) and (Dshooter2player<=missile.missileRange*1.5 or dist<=self.explosiondist) then
|
||||
mindist=dist
|
||||
target=player.unit
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.protectedset then
|
||||
|
||||
-- Distance to closest protected unit.
|
||||
mindist=nil
|
||||
|
||||
for _,_group in pairs(self.protectedset:GetSet()) do
|
||||
local group=_group --Wrapper.Group#GROUP
|
||||
for _,_unit in pairs(group:GetUnits()) do
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
if unit and unit:IsAlive() then
|
||||
|
||||
-- Check that player was not the one who launched the missile.
|
||||
if unit:GetName()~=missile.shooterName then
|
||||
|
||||
-- Player position.
|
||||
local playerCoord=unit:GetCoordinate()
|
||||
|
||||
-- Distance.
|
||||
local dist=missileCoord:Get3DDistance(playerCoord)
|
||||
|
||||
-- Distance from shooter to player.
|
||||
local Dshooter2player=playerCoord:Get3DDistance(missile.shotCoord)
|
||||
|
||||
-- Update mindist if necessary. Only include players in range of missile + 50% safety margin.
|
||||
if (mindist==nil or dist<mindist) and (Dshooter2player<=missile.missileRange*1.5 or dist<=self.explosiondist) then
|
||||
mindist=dist
|
||||
target=unit
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if target then
|
||||
self:I(self.lid..string.format("Missile %s with NO explicit target got closest unit to missile as target %s. Dist=%s m", missile.missileType, target:GetName(), tostring(mindist)))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Check if missile has a valid target.
|
||||
@@ -865,39 +974,69 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
||||
-- Distance from missile to target.
|
||||
local distance=missileCoord:Get3DDistance(targetCoord)
|
||||
|
||||
local bearing=targetCoord:HeadingTo(missileCoord)
|
||||
local eta=distance/missileVelocity
|
||||
-- Distance missile to shooter.
|
||||
local distShooter=nil
|
||||
if missile.shooterUnit and missile.shooterUnit:IsAlive() then
|
||||
distShooter=missileCoord:Get3DDistance(missile.shooterUnit:GetCoordinate())
|
||||
end
|
||||
|
||||
self:T2(self.lid..string.format("Distance = %.1f m, v=%.1f m/s, bearing=%03d°, eta=%.1f sec", distance, missileVelocity, bearing, eta))
|
||||
|
||||
-- Debug output.
|
||||
if self.Debug then
|
||||
local bearing=targetCoord:HeadingTo(missileCoord)
|
||||
local eta=distance/missileVelocity
|
||||
|
||||
-- Debug distance check.
|
||||
self:I(self.lid..string.format("Missile %s Target %s: Distance = %.1f m, v=%.1f m/s, bearing=%03d°, ETA=%.1f sec", missile.missileType, target:GetName(), distance, missileVelocity, bearing, eta))
|
||||
end
|
||||
|
||||
-- Distroy missile if it's getting too close.
|
||||
local destroymissile=distance<=self.explosiondist
|
||||
|
||||
-- Check BIG missiles.
|
||||
if self.explosiondist2 and distance<=self.explosiondist2 and not destroymissile then
|
||||
destroymissile=missile.explosive>=self.bigmissilemass
|
||||
end
|
||||
|
||||
-- If missile is 100 m from target ==> destroy missile if in safe zone.
|
||||
if distance<=self.explosiondist and self:_CheckCoordSafe(targetCoord)then
|
||||
-- If missile is 150 m from target ==> destroy missile if in safe zone.
|
||||
if destroymissile and self:_CheckCoordSafe(targetCoord) then
|
||||
|
||||
-- Destroy missile.
|
||||
self:T(self.lid..string.format("Destroying missile at distance %.1f m", distance))
|
||||
self:I(self.lid..string.format("Destroying missile %s(%s) fired by %s aimed at %s [player=%s] at distance %.1f m",
|
||||
missile.missileType, missile.missileName, missile.shooterName, target:GetName(), tostring(missile.targetPlayer~=nil), distance))
|
||||
_ordnance:destroy()
|
||||
|
||||
-- Missile is not active any more.
|
||||
missile.active=false
|
||||
|
||||
-- Debug smoke.
|
||||
if self.Debug then
|
||||
missileCoord:SmokeRed()
|
||||
targetCoord:SmokeGreen()
|
||||
end
|
||||
|
||||
-- Create event.
|
||||
self:MissileDestroyed(missile)
|
||||
|
||||
-- Little explosion for the visual effect.
|
||||
if self.explosionpower>0 then
|
||||
if self.explosionpower>0 and distance>50 and (distShooter==nil or (distShooter and distShooter>50)) then
|
||||
missileCoord:Explosion(self.explosionpower)
|
||||
end
|
||||
|
||||
local text=string.format("Destroying missile. %s", self:_DeadText())
|
||||
MESSAGE:New(text, 10):ToGroup(target:GetGroup())
|
||||
|
||||
-- Increase dead counter.
|
||||
|
||||
-- Target was a player.
|
||||
if missile.targetPlayer then
|
||||
|
||||
-- Message to target.
|
||||
local text=string.format("Destroying missile. %s", self:_DeadText())
|
||||
MESSAGE:New(text, 10):ToGroup(target:GetGroup())
|
||||
|
||||
-- Increase dead counter.
|
||||
missile.targetPlayer.dead=missile.targetPlayer.dead+1
|
||||
end
|
||||
|
||||
-- Terminate timer.
|
||||
return nil
|
||||
|
||||
else
|
||||
|
||||
-- Time step.
|
||||
@@ -922,10 +1061,15 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
||||
-- Check again in dt seconds.
|
||||
return timer.getTime()+dt
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Destroy missile.
|
||||
self:I(self.lid..string.format("Missile %s(%s) fired by %s has no current target. Checking back in 0.1 sec.", missile.missileType, missile.missileName, missile.shooterName))
|
||||
return timer.getTime()+0.1
|
||||
|
||||
-- No target ==> terminate timer.
|
||||
return nil
|
||||
--return nil
|
||||
end
|
||||
|
||||
else
|
||||
@@ -945,7 +1089,7 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
||||
MESSAGE:New(text, 10):ToClient(player.client)
|
||||
|
||||
-- Increase defeated counter.
|
||||
player.defeated=player.defeated+1
|
||||
player.defeated=player.defeated+1
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1041,11 +1185,52 @@ function FOX:OnEventBirth(EventData)
|
||||
end
|
||||
end
|
||||
|
||||
--- Get missile target.
|
||||
-- @param #FOX self
|
||||
-- @param #FOX.MissileData missile The missile data table.
|
||||
function FOX:GetMissileTarget(missile)
|
||||
|
||||
local target=nil
|
||||
local targetName="unknown"
|
||||
local targetUnit=nil --Wrapper.Unit#UNIT
|
||||
|
||||
if missile.weapon and missile.weapon:isExist() then
|
||||
|
||||
-- Get target of missile.
|
||||
target=missile.weapon:getTarget()
|
||||
|
||||
-- Get the target unit. Note if if _target is not nil, the unit can sometimes not be found!
|
||||
if target then
|
||||
self:T2({missiletarget=target})
|
||||
|
||||
-- Get target unit.
|
||||
targetUnit=UNIT:Find(target)
|
||||
|
||||
if targetUnit then
|
||||
targetName=targetUnit:GetName()
|
||||
|
||||
missile.targetUnit=targetUnit
|
||||
missile.targetPlayer=self:_GetPlayerFromUnit(missile.targetUnit)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- Missile got new target.
|
||||
if missile.targetName and missile.targetName~=targetName then
|
||||
self:I(self.lid..string.format("Missile %s(%s) changed target to %s. Previous target was %s.", missile.missileType, missile.missileName, targetName, missile.targetName))
|
||||
end
|
||||
|
||||
-- Set target name.
|
||||
missile.targetName=targetName
|
||||
|
||||
end
|
||||
|
||||
--- FOX event handler for event shot (when a unit releases a rocket or bomb (but not a fast firing gun).
|
||||
-- @param #FOX self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function FOX:OnEventShot(EventData)
|
||||
self:I({eventshot = EventData})
|
||||
self:T2({eventshot=EventData})
|
||||
|
||||
if EventData.Weapon==nil then
|
||||
return
|
||||
@@ -1062,7 +1247,7 @@ function FOX:OnEventShot(EventData)
|
||||
|
||||
-- Weapon descriptor.
|
||||
local desc=EventData.Weapon:getDesc()
|
||||
self:E({desc=desc})
|
||||
self:T2({desc=desc})
|
||||
|
||||
-- Weapon category: 0=Shell, 1=Missile, 2=Rocket, 3=BOMB
|
||||
local weaponcategory=desc.category
|
||||
@@ -1091,15 +1276,6 @@ function FOX:OnEventShot(EventData)
|
||||
return
|
||||
end
|
||||
|
||||
-- Get the target unit. Note if if _target is not nil, the unit can sometimes not be found!
|
||||
if _target then
|
||||
self:E({target=_target})
|
||||
--_targetName=Unit.getName(_target)
|
||||
--_targetUnit=UNIT:FindByName(_targetName)
|
||||
_targetUnit=UNIT:Find(_target)
|
||||
end
|
||||
self:E(FOX.lid..string.format("EVENT SHOT: Target name = %s", tostring(_targetName)))
|
||||
|
||||
-- Track missiles of type AAM=1, SAM=2 or OTHER=6
|
||||
local _track = weaponcategory==1 and missilecategory and (missilecategory==1 or missilecategory==2 or missilecategory==6)
|
||||
|
||||
@@ -1119,11 +1295,18 @@ function FOX:OnEventShot(EventData)
|
||||
missile.shooterName=EventData.IniUnitName
|
||||
missile.shotTime=timer.getAbsTime()
|
||||
missile.shotCoord=EventData.IniUnit:GetCoordinate()
|
||||
missile.targetUnit=_targetUnit
|
||||
missile.targetPlayer=self:_GetPlayerFromUnit(missile.targetUnit)
|
||||
missile.fuseDist=desc.fuseDist
|
||||
missile.explosive=desc.warhead.explosiveMass or desc.warhead.shapedExplosiveMass
|
||||
missile.targetOrig=missile.targetName
|
||||
|
||||
-- Only track if target was a player or target is protected.
|
||||
if missile.targetPlayer or self:_IsProtected(missile.targetUnit) then
|
||||
-- Set missile target name, unit and player.
|
||||
self:GetMissileTarget(missile)
|
||||
|
||||
self:I(FOX.lid..string.format("EVENT SHOT: Shooter=%s %s(%s) ==> Target=%s, fuse dist=%s, explosive=%s",
|
||||
tostring(missile.shooterName), tostring(missile.missileType), tostring(missile.missileName), tostring(missile.targetName), tostring(missile.fuseDist), tostring(missile.explosive)))
|
||||
|
||||
-- Only track if target was a player or target is protected. Saw the 9M311 missiles have no target!
|
||||
if missile.targetPlayer or self:_IsProtected(missile.targetUnit) or missile.targetName=="unknown" then
|
||||
|
||||
-- Add missile table.
|
||||
table.insert(self.missiles, missile)
|
||||
@@ -1137,6 +1320,36 @@ function FOX:OnEventShot(EventData)
|
||||
|
||||
end
|
||||
|
||||
--- FOX event handler for event hit.
|
||||
-- @param #FOX self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function FOX:OnEventHit(EventData)
|
||||
self:T({eventhit = EventData})
|
||||
|
||||
-- Nil checks.
|
||||
if EventData.Weapon==nil then
|
||||
return
|
||||
end
|
||||
if EventData.IniUnit==nil then
|
||||
return
|
||||
end
|
||||
if EventData.TgtUnit==nil then
|
||||
return
|
||||
end
|
||||
|
||||
local weapon=EventData.Weapon
|
||||
local weaponname=weapon:getName()
|
||||
|
||||
for i,_missile in pairs(self.missiles) do
|
||||
local missile=_missile --#FOX.MissileData
|
||||
if missile.missileName==weaponname then
|
||||
self:I(self.lid..string.format("WARNING: Missile %s (%s) hit target %s. Missile trainer target was %s.", missile.missileType, missile.missileName, EventData.TgtUnitName, missile.targetName))
|
||||
self:I({missile=missile})
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- RADIO MENU Functions
|
||||
|
||||
@@ -57,8 +57,10 @@ SEAD = {
|
||||
-- -- Defends the Russian SA installations from SEAD attacks.
|
||||
-- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } )
|
||||
function SEAD:New( SEADGroupPrefixes )
|
||||
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:F( SEADGroupPrefixes )
|
||||
self:F( SEADGroupPrefixes )
|
||||
|
||||
if type( SEADGroupPrefixes ) == 'table' then
|
||||
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
|
||||
self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix
|
||||
@@ -85,7 +87,29 @@ function SEAD:OnEventShot( EventData )
|
||||
local SEADWeaponName = EventData.WeaponName -- return weapon type
|
||||
-- Start of the 2nd loop
|
||||
self:T( "Missile Launched = " .. SEADWeaponName )
|
||||
if SEADWeaponName == "KH-58" or SEADWeaponName == "KH-25MPU" or SEADWeaponName == "AGM-88" or SEADWeaponName == "KH-31A" or SEADWeaponName == "KH-31P" then -- Check if the missile is a SEAD
|
||||
|
||||
--if SEADWeaponName == "KH-58" or SEADWeaponName == "KH-25MPU" or SEADWeaponName == "AGM-88" or SEADWeaponName == "KH-31A" or SEADWeaponName == "KH-31P" then -- Check if the missile is a SEAD
|
||||
if SEADWeaponName == "weapons.missiles.X_58" --Kh-58U anti-radiation missiles fired
|
||||
or
|
||||
SEADWeaponName == "weapons.missiles.Kh25MP_PRGS1VP" --Kh-25MP anti-radiation missiles fired
|
||||
or
|
||||
SEADWeaponName == "weapons.missiles.X_25MP" --Kh-25MPU anti-radiation missiles fired
|
||||
or
|
||||
SEADWeaponName == "weapons.missiles.X_28" --Kh-28 anti-radiation missiles fired
|
||||
or
|
||||
SEADWeaponName == "weapons.missiles.X_31P" --Kh-31P anti-radiation missiles fired
|
||||
or
|
||||
SEADWeaponName == "weapons.missiles.AGM_45A" --AGM-45A anti-radiation missiles fired
|
||||
or
|
||||
SEADWeaponName == "weapons.missiles.AGM_45" --AGM-45B anti-radiation missiles fired
|
||||
or
|
||||
SEADWeaponName == "weapons.missiles.AGM_88" --AGM-88C anti-radiation missiles fired
|
||||
or
|
||||
SEADWeaponName == "weapons.missiles.AGM_122" --AGM-122 Sidearm anti-radiation missiles fired
|
||||
or
|
||||
SEADWeaponName == "weapons.missiles.ALARM" --ALARM anti-radiation missiles fired
|
||||
then
|
||||
|
||||
local _evade = math.random (1,100) -- random number for chance of evading action
|
||||
local _targetMim = EventData.Weapon:getTarget() -- Identify target
|
||||
local _targetMimname = Unit.getName(_targetMim)
|
||||
@@ -111,47 +135,62 @@ function SEAD:OnEventShot( EventData )
|
||||
self:T( _targetskill )
|
||||
if self.TargetSkill[_targetskill] then
|
||||
if (_evade > self.TargetSkill[_targetskill].Evade) then
|
||||
|
||||
self:T( string.format("Evading, target skill " ..string.format(_targetskill)) )
|
||||
|
||||
local _targetMim = Weapon.getTarget(SEADWeapon)
|
||||
local _targetMimname = Unit.getName(_targetMim)
|
||||
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon))
|
||||
local _targetMimcont= _targetMimgroup:getController()
|
||||
|
||||
routines.groupRandomDistSelf(_targetMimgroup,300,'Diamond',250,20) -- move randomly
|
||||
|
||||
local SuppressedGroups1 = {} -- unit suppressed radar off for a random time
|
||||
|
||||
local function SuppressionEnd1(id)
|
||||
id.ctrl:setOption(AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.GREEN)
|
||||
SuppressedGroups1[id.groupName] = nil
|
||||
end
|
||||
|
||||
local id = {
|
||||
groupName = _targetMimgroup,
|
||||
ctrl = _targetMimcont
|
||||
}
|
||||
|
||||
local delay1 = math.random(self.TargetSkill[_targetskill].DelayOff[1], self.TargetSkill[_targetskill].DelayOff[2])
|
||||
|
||||
if SuppressedGroups1[id.groupName] == nil then
|
||||
|
||||
SuppressedGroups1[id.groupName] = {
|
||||
SuppressionEndTime1 = timer.getTime() + delay1,
|
||||
SuppressionEndN1 = SuppressionEndCounter1 --Store instance of SuppressionEnd() scheduled function
|
||||
}
|
||||
}
|
||||
|
||||
Controller.setOption(_targetMimcont, AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.GREEN)
|
||||
timer.scheduleFunction(SuppressionEnd1, id, SuppressedGroups1[id.groupName].SuppressionEndTime1) --Schedule the SuppressionEnd() function
|
||||
--trigger.action.outText( string.format("Radar Off " ..string.format(delay1)), 20)
|
||||
end
|
||||
|
||||
local SuppressedGroups = {}
|
||||
|
||||
local function SuppressionEnd(id)
|
||||
id.ctrl:setOption(AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.RED)
|
||||
SuppressedGroups[id.groupName] = nil
|
||||
end
|
||||
|
||||
local id = {
|
||||
groupName = _targetMimgroup,
|
||||
ctrl = _targetMimcont
|
||||
}
|
||||
|
||||
local delay = math.random(self.TargetSkill[_targetskill].DelayOn[1], self.TargetSkill[_targetskill].DelayOn[2])
|
||||
|
||||
if SuppressedGroups[id.groupName] == nil then
|
||||
SuppressedGroups[id.groupName] = {
|
||||
SuppressionEndTime = timer.getTime() + delay,
|
||||
SuppressionEndN = SuppressionEndCounter --Store instance of SuppressionEnd() scheduled function
|
||||
}
|
||||
|
||||
timer.scheduleFunction(SuppressionEnd, id, SuppressedGroups[id.groupName].SuppressionEndTime) --Schedule the SuppressionEnd() function
|
||||
--trigger.action.outText( string.format("Radar On " ..string.format(delay)), 20)
|
||||
end
|
||||
|
||||
@@ -77,6 +77,8 @@
|
||||
-- @field #boolean safeparking If true, parking spots for aircraft are considered as occupied if e.g. a client aircraft is parked there. Default false.
|
||||
-- @field #boolean isunit If true, warehouse is represented by a unit instead of a static.
|
||||
-- @field #number lowfuelthresh Low fuel threshold. Triggers the event AssetLowFuel if for any unit fuel goes below this number.
|
||||
-- @field #boolean respawnafterdestroyed If true, warehouse is respawned after it was destroyed. Assets are kept.
|
||||
-- @field #number respawndelay Delay before respawn in seconds.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- Have your assets at the right place at the right time - or not!
|
||||
@@ -1569,6 +1571,8 @@ WAREHOUSE = {
|
||||
saveparking = false,
|
||||
isunit = false,
|
||||
lowfuelthresh = 0.15,
|
||||
respawnafterdestroyed=false,
|
||||
respawndelay = nil,
|
||||
}
|
||||
|
||||
--- Item of the warehouse stock table.
|
||||
@@ -1747,7 +1751,7 @@ _WAREHOUSEDB = {
|
||||
|
||||
--- Warehouse class version.
|
||||
-- @field #string version
|
||||
WAREHOUSE.version="0.9.4"
|
||||
WAREHOUSE.version="0.9.5"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO: Warehouse todo list.
|
||||
@@ -1910,6 +1914,7 @@ function WAREHOUSE:New(warehouse, alias)
|
||||
self:AddTransition("*", "AirbaseRecaptured", "*") -- Airbase was re-captured from other coalition.
|
||||
self:AddTransition("*", "AssetDead", "*") -- An asset group died.
|
||||
self:AddTransition("*", "Destroyed", "Destroyed") -- Warehouse was destroyed. All assets in stock are gone and warehouse is stopped.
|
||||
self:AddTransition("Destroyed", "Respawn", "Running") -- Respawn warehouse after it was destroyed.
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
@@ -1942,6 +1947,22 @@ function WAREHOUSE:New(warehouse, alias)
|
||||
-- @param #WAREHOUSE self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- Triggers the FSM event "Respawn".
|
||||
-- @function [parent=#WAREHOUSE] Respawn
|
||||
-- @param #WAREHOUSE self
|
||||
|
||||
--- Triggers the FSM event "Respawn" after a delay.
|
||||
-- @function [parent=#WAREHOUSE] __Respawn
|
||||
-- @param #WAREHOUSE self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- On after "Respawn" event user function.
|
||||
-- @function [parent=#WAREHOUSE] OnAfterRespawn
|
||||
-- @param #WAREHOUSE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- Triggers the FSM event "Pause". Pauses the warehouse. Assets can still be added and requests be made. However, requests are not processed.
|
||||
-- @function [parent=#WAREHOUSE] Pause
|
||||
-- @param #WAREHOUSE self
|
||||
@@ -2535,6 +2556,15 @@ function WAREHOUSE:SetSaveOnMissionEnd(path, filename)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set respawn after destroy.
|
||||
-- @param #WAREHOUSE self
|
||||
-- @return #WAREHOUSE self
|
||||
function WAREHOUSE:SetRespawnAfterDestroyed(delay)
|
||||
self.respawnafterdestroyed=true
|
||||
self.respawndelay=delay
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set the airbase belonging to this warehouse.
|
||||
-- Note that it has to be of the same coalition as the warehouse.
|
||||
@@ -3964,7 +3994,7 @@ function WAREHOUSE:onbeforeAddRequest(From, Event, To, warehouse, AssetDescripto
|
||||
end
|
||||
|
||||
-- Warehouse is destroyed?
|
||||
if self:IsDestroyed() then
|
||||
if self:IsDestroyed() and not self.respawnafterdestroyed then
|
||||
self:_ErrorMessage("ERROR: Invalid request. Warehouse is destroyed!", 0)
|
||||
okay=false
|
||||
end
|
||||
@@ -4348,9 +4378,9 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
|
||||
table.insert(_transportassets,_assetitem)
|
||||
|
||||
-- Spawned into the world.
|
||||
_assetitem.spawned=true
|
||||
_assetitem.spawned=true
|
||||
_assetitem.spawngroupname=spawngroup:GetName()
|
||||
|
||||
|
||||
-- Asset spawned FSM function.
|
||||
self:__AssetSpawned(1, spawngroup, _assetitem, Request)
|
||||
end
|
||||
@@ -4835,6 +4865,21 @@ function WAREHOUSE:onbeforeChangeCountry(From, Event, To, Country)
|
||||
return false
|
||||
end
|
||||
|
||||
--- Respawn warehouse.
|
||||
-- @param #WAREHOUSE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function WAREHOUSE:onafterRespawn(From, Event, To)
|
||||
|
||||
-- Info message.
|
||||
local text=string.format("Respawning warehouse %s.", self.alias)
|
||||
self:_InfoMessage(text)
|
||||
|
||||
-- Respawn warehouse.
|
||||
self.warehouse:ReSpawn()
|
||||
|
||||
end
|
||||
|
||||
--- On after "ChangeCountry" event. Warehouse is respawned with the specified country. All queued requests are deleted and the owned airbase is reset if the coalition is changed by changing the
|
||||
-- country.
|
||||
@@ -4949,7 +4994,7 @@ function WAREHOUSE:onafterAirbaseRecaptured(From, Event, To, Coalition)
|
||||
end
|
||||
|
||||
|
||||
--- On after "AssetDead" event triggerd when an asset group died.
|
||||
--- On after "AssetDead" event triggered when an asset group died.
|
||||
-- @param #WAREHOUSE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
@@ -4971,22 +5016,34 @@ end
|
||||
function WAREHOUSE:onafterDestroyed(From, Event, To)
|
||||
|
||||
-- Message.
|
||||
local text=string.format("Warehouse %s was destroyed! Assets lost %d.", self.alias, #self.stock)
|
||||
local text=string.format("Warehouse %s was destroyed! Assets lost %d. Respawn=%s", self.alias, #self.stock, tostring(self.respawnafterdestroyed))
|
||||
self:_InfoMessage(text)
|
||||
|
||||
-- Remove all table entries from waiting queue and stock.
|
||||
for k,_ in pairs(self.queue) do
|
||||
self.queue[k]=nil
|
||||
end
|
||||
for k,_ in pairs(self.stock) do
|
||||
self.stock[k]=nil
|
||||
end
|
||||
if self.respawnafterdestroyed then
|
||||
|
||||
--self.queue=nil
|
||||
--self.queue={}
|
||||
if self.respawndelay then
|
||||
self:Pause()
|
||||
self:__Respawn(self.respawndelay)
|
||||
else
|
||||
self:Respawn()
|
||||
end
|
||||
|
||||
--self.stock=nil
|
||||
--self.stock={}
|
||||
else
|
||||
|
||||
-- Remove all table entries from waiting queue and stock.
|
||||
for k,_ in pairs(self.queue) do
|
||||
self.queue[k]=nil
|
||||
end
|
||||
for k,_ in pairs(self.stock) do
|
||||
self.stock[k]=nil
|
||||
end
|
||||
|
||||
--self.queue=nil
|
||||
--self.queue={}
|
||||
|
||||
--self.stock=nil
|
||||
--self.stock={}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5289,7 +5346,7 @@ function WAREHOUSE:_SpawnAssetRequest(Request)
|
||||
if _group then
|
||||
_groupset:AddGroup(_group)
|
||||
table.insert(_assets, _assetitem)
|
||||
|
||||
|
||||
-- Spawned into the world.
|
||||
_assetitem.spawned=true
|
||||
_assetitem.spawngroupname=_group:GetName()
|
||||
@@ -6355,7 +6412,7 @@ function WAREHOUSE:_CheckRequestConsistancy(queue)
|
||||
end
|
||||
|
||||
-- Is receiving warehouse destroyed?
|
||||
if request.warehouse:IsDestroyed() then
|
||||
if request.warehouse:IsDestroyed() and not self.respawnafterdestroyed then
|
||||
self:E(self.wid..string.format("ERROR: INVALID request. Requesting warehouse is destroyed!"))
|
||||
valid=false
|
||||
end
|
||||
@@ -7779,7 +7836,7 @@ function WAREHOUSE:_CheckFuel()
|
||||
local group=_group --Wrapper.Group#GROUP
|
||||
|
||||
if group and group:IsAlive() then
|
||||
|
||||
|
||||
-- Get min fuel of group.
|
||||
local fuel=group:GetFuelMin()
|
||||
|
||||
@@ -7788,11 +7845,11 @@ function WAREHOUSE:_CheckFuel()
|
||||
|
||||
-- Check if fuel is below threshold for first time.
|
||||
if fuel<self.lowfuelthresh and not qitem.lowfuel then
|
||||
|
||||
|
||||
-- Set low fuel flag.
|
||||
self:I(self.wid..string.format("Transport group %s is low on fuel! Min fuel state = %.2f", group:GetName(), fuel))
|
||||
qitem.lowfuel=true
|
||||
|
||||
|
||||
-- Trigger low fuel event.
|
||||
local asset=self:FindAssetInDB(group)
|
||||
self:AssetLowFuel(asset, qitem)
|
||||
@@ -7817,11 +7874,11 @@ function WAREHOUSE:_CheckFuel()
|
||||
|
||||
-- Check if fuel is below threshold for first time.
|
||||
if fuel<self.lowfuelthresh and not qitem.lowfuel then
|
||||
|
||||
|
||||
-- Set low fuel flag.
|
||||
self:I(self.wid..string.format("Cargo group %s is low on fuel! Min fuel state = %.2f", group:GetName(), fuel))
|
||||
qitem.lowfuel=true
|
||||
|
||||
|
||||
-- Trigger low fuel event.
|
||||
local asset=self:FindAssetInDB(group)
|
||||
self:AssetLowFuel(asset, qitem)
|
||||
|
||||
Reference in New Issue
Block a user