mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-11 19:58:22 +00:00
Ops
This commit is contained in:
@@ -85,6 +85,8 @@ AIRWING.version="0.1.3"
|
||||
-- TODO: Check if missions are accomplished.
|
||||
-- DONE: Payloads as resources.
|
||||
-- TODO: Spawn in air or hot.
|
||||
-- TODO: Define CAP zones.
|
||||
-- TODO: Define TANKER zones for refuelling.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
-- @field Wrapper.Group#GROUP escortGroup The group to be escorted.
|
||||
-- @field DCS#Vec3 escortVec3 The 3D offset vector from the escorted group to the escort group.
|
||||
--
|
||||
-- @field Ops.AirWing#AIRWING airwing The assigned airwing.
|
||||
-- @field #string squadname Name of the assigned Airwing squadron.
|
||||
-- @field #table assets Airwing Assets assigned for this mission.
|
||||
-- @field #number nassets Number of required assets by the Airwing.
|
||||
@@ -436,6 +437,13 @@ function AUFTRAG:SetWeaponType(WeaponType)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Check if mission is executing.
|
||||
-- @param #AUFTRAG self
|
||||
-- @return #boolean If true, mission is currently executing.
|
||||
function AUFTRAG:IsExecuting()
|
||||
return self.status==AUFTRAG.Status.EXECUTING
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -525,7 +533,7 @@ end
|
||||
|
||||
--- Get coordinate of target. First unit/group of the set is used.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Core.Point#COORDINATE The target coordinate or nil.
|
||||
-- @return Core.Point#COORDINATE The target coordinate or nil.
|
||||
function AUFTRAG:GetTargetCoordinate()
|
||||
|
||||
if self.engageTargetGroupset then
|
||||
|
||||
@@ -3140,7 +3140,6 @@ function FLIGHTGROUP:onafterMissionStart(From, Event, To, Mission)
|
||||
|
||||
-- Set mission status.
|
||||
Mission:Start()
|
||||
--Mission.status=AUFTRAG.Status.STARTED
|
||||
|
||||
-- Route flight to mission zone.
|
||||
self:RouteToMission(Mission, 5)
|
||||
@@ -3159,19 +3158,20 @@ function FLIGHTGROUP:onafterMissionExecute(From, Event, To, Mission)
|
||||
self:I(self.lid..text)
|
||||
MESSAGE:New(text, 120, "DEBUG"):ToAllIf(true)
|
||||
|
||||
-- Set mission status.
|
||||
Mission:Execute()
|
||||
--Mission.status=AUFTRAG.Status.EXECUTING
|
||||
|
||||
end
|
||||
|
||||
--- On after "MissionCancel" event. Cancels the current mission.
|
||||
--- On after "MissionCancel" event. Cancels the mission.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FLIGHTGROUP:onafterMissionCancel(From, Event, To)
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission to be cancelled.
|
||||
function FLIGHTGROUP:onafterMissionCancel(From, Event, To, Mission)
|
||||
|
||||
if self.currentmission then
|
||||
if Mission.auftragsnummer==self.currentmission then
|
||||
|
||||
-- Cancelling the mission is actually cancelling the current task.
|
||||
self:TaskCancel()
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
-- @field #boolean Debug Debug mode. Messages to all about status.
|
||||
-- @field #string lid Class id string for output to DCS log file.
|
||||
-- @field #table filter Category filters.
|
||||
-- @field #table DetectedItems Table of detected items.
|
||||
-- @field #table Contacts Table of detected items.
|
||||
-- @field #table ContactsLost Table of lost detected items.
|
||||
-- @field #table ContactsUnknown Table of new detected items.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- Be surprised!
|
||||
@@ -32,13 +34,14 @@
|
||||
--
|
||||
-- @field #INTEL
|
||||
INTEL = {
|
||||
ClassName = "INTEL",
|
||||
Debug = nil,
|
||||
lid = nil,
|
||||
filter = nil,
|
||||
detectionset = nil,
|
||||
DetectedItems = {},
|
||||
DetectedGroups = {},
|
||||
ClassName = "INTEL",
|
||||
Debug = nil,
|
||||
lid = nil,
|
||||
filter = nil,
|
||||
detectionset = nil,
|
||||
Contacts = {},
|
||||
ContactsLost = {},
|
||||
ContactsUnknown = {},
|
||||
}
|
||||
|
||||
--- Detected item info.
|
||||
@@ -56,7 +59,7 @@ INTEL = {
|
||||
|
||||
--- INTEL class version.
|
||||
-- @field #string version
|
||||
INTEL.version="0.0.1"
|
||||
INTEL.version="0.0.2"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
@@ -87,9 +90,6 @@ function INTEL:New(DetectionSet)
|
||||
-- Start State.
|
||||
self:SetStartState("Stopped")
|
||||
|
||||
-- Init set of detected units.
|
||||
self.detectedunits=SET_UNIT:New()
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
|
||||
@@ -97,12 +97,8 @@ function INTEL:New(DetectionSet)
|
||||
|
||||
self:AddTransition("*", "Detect", "*") -- INTEL status update
|
||||
|
||||
self:AddTransition("*", "DetectedUnit", "*") --
|
||||
|
||||
self:AddTransition("*", "DetectedGroups", "*") -- All groups that are currently detected.
|
||||
self:AddTransition("*", "DetectedGroupsUnknown", "*") -- Newly detected groups, which were previously unknown.
|
||||
self:AddTransition("*", "DetectedGroupsDead", "*") -- Previously detected groups that could not be detected any more.
|
||||
self:AddTransition("*", "DetectedGroupsLost", "*") -- Previously detected groups that could not be detected any more.
|
||||
self:AddTransition("*", "NewContact", "*") --
|
||||
self:AddTransition("*", "LostContact", "*") --
|
||||
|
||||
|
||||
------------------------
|
||||
@@ -153,12 +149,21 @@ end
|
||||
-- User functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set livery.
|
||||
--- Set accept zones.
|
||||
-- @param #INTEL self
|
||||
-- @param #string liveryname Name of the livery.
|
||||
-- @param Core.Set#SET_ZONE AcceptZoneSet Set of accept zones
|
||||
-- @return #INTEL self
|
||||
function INTEL:SetLivery(liveryname)
|
||||
self.livery=liveryname
|
||||
function INTEL:SetAcceptZones(AcceptZoneSet)
|
||||
self.acceptzoneset=AcceptZoneSet or SET_ZONE:New()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set accept zones.
|
||||
-- @param #INTEL self
|
||||
-- @param Core.Zone#ZONE AcceptZone Add a zone to the accept zone set.
|
||||
-- @return #INTEL self
|
||||
function INTEL:AddAcceptZone(AcceptZone)
|
||||
self.acceptzoneset=nil
|
||||
end
|
||||
|
||||
|
||||
@@ -175,7 +180,7 @@ end
|
||||
function INTEL:onafterStart(From, Event, To)
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("Starting flight group %s.", self.groupname)
|
||||
local text=string.format("Starting INTEL v%s.", self.version)
|
||||
self:I(self.sid..text)
|
||||
|
||||
-- Start the status monitoring.
|
||||
@@ -197,8 +202,8 @@ function INTEL:onafterStatus(From, Event, To)
|
||||
self:UpdateIntel()
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("Flight status %s [%d/%d]. Task=%d/%d. Waypoint=%d/%d. Detected=%d", fsmstate, #self.element, #self.element, self.taskcurrent, #self.taskqueue, self.currentwp or 0, #self.waypoints or 0, self.detectedunits:Count())
|
||||
self:I(self.sid..text)
|
||||
local text=string.format("Status=%s", fsmstate)
|
||||
self:I(self.lid..text)
|
||||
|
||||
|
||||
self:__Status(-30)
|
||||
@@ -224,12 +229,22 @@ function INTEL:UpdateIntel()
|
||||
|
||||
end
|
||||
|
||||
-- TODO: Filter units from accept/reject zones.
|
||||
-- TODO: Filter unit types.
|
||||
-- TODO: Filter detection methods?
|
||||
|
||||
self:CreateDetectedItems(DetectedSet)
|
||||
|
||||
--[[
|
||||
|
||||
-- Newly detected units.
|
||||
local detectednew=DetectedSet:GetSetComplement(self.detectedunits)
|
||||
|
||||
-- Previously detected units which got lost.
|
||||
local detectedlost=self.detectedunits:GetSetComplement(DetectedSet)
|
||||
|
||||
]]
|
||||
|
||||
-- TODO: Loose units only if they remain undetected for a given time interval. We want to avoid fast oscillation between detected/lost states. Maybe 1-5 min would be a good time interval?!
|
||||
-- TODO: Combine units to groups for all, new and lost.
|
||||
-- TODO: process detected set asynchroniously for better performance.
|
||||
@@ -259,34 +274,90 @@ function INTEL:CreateDetectedItems(detectedunitset)
|
||||
for _,_group in pairs(detectedgroupset.Set) do
|
||||
local group=_group --Wrapper.Group#GROUP
|
||||
|
||||
local detecteditem=self:GetDetectedItemByName(group:GetName())
|
||||
local groupname=group:GetName()
|
||||
|
||||
local detecteditem=self:GetContactByName(groupname)
|
||||
|
||||
if detecteditem then
|
||||
---
|
||||
-- Detected item already exists ==> Update data.
|
||||
---
|
||||
|
||||
|
||||
detecteditem.Tdetected=timer.getAbsTime()
|
||||
detecteditem.position=group:GetCoordinate()
|
||||
|
||||
else
|
||||
---
|
||||
-- Detected item does not exist in our list yet.
|
||||
---
|
||||
|
||||
local item={} --#INTEL.DetectedItem
|
||||
|
||||
item.groupname=groupname
|
||||
item.Tdetected=timer.getAbsTime()
|
||||
item.group=group
|
||||
item.position=group:GetCoordinate()
|
||||
item.typename=group:GetTypeName()
|
||||
item.attribute=group:GetAttribute()
|
||||
item.category=group:GetCategory()
|
||||
item.categoryname=group:GetCategoryName()
|
||||
|
||||
self:AddContact(item)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Now check if there some groups could not be detected any more.
|
||||
for i=#self.Contacts,1,-1 do
|
||||
local item=self.Contacts[i] --#INTEL.DetectedItem
|
||||
|
||||
local group=detectedgroupset:FindGroup(item.groupname)
|
||||
|
||||
if not group then
|
||||
--TODO: check if deltaT>Tforget. we dont want quick oszillations between detected and undetected states.
|
||||
self:RemoveContact(item)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Create detected items.
|
||||
-- @param #INTEL self
|
||||
-- @param #string name Name of the detected item.
|
||||
-- @param #string groupname Name of the contact group.
|
||||
-- @return #INTEL.DetectedItem
|
||||
function INTEL:GetDetectedItemByName(name)
|
||||
function INTEL:GetContactByName(groupname)
|
||||
|
||||
return self.DetectedItems[name]
|
||||
for i,_contact in pairs(self.Contacts) do
|
||||
local contact=_contact --#INTEL.DetectedItem
|
||||
if contact.groupname==groupname then
|
||||
return contact
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Remove a contact from our list.
|
||||
-- @param #INTEL self
|
||||
-- @param #INTEL.DetectedItem Contact The contact to be removed.
|
||||
function INTEL:RemoveContact(Contact)
|
||||
|
||||
for i,_contact in pairs(self.Contacts) do
|
||||
local contact=_contact --#INTEL.DetectedItem
|
||||
|
||||
if contact.groupname==Contact.groupname then
|
||||
table.remove(self.Contacts, i)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Remove a contact from our list.
|
||||
-- @param #INTEL self
|
||||
-- @param #INTEL.DetectedItem Contact The contact to be removed.
|
||||
function INTEL:AddContact(Contact)
|
||||
table.insert(self.Contacts, Contact)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
-- @field #boolean Debug Debug mode. Messages to all about status.
|
||||
-- @field #string lid Class id string for output to DCS log file.
|
||||
-- @field #table airwings Table of airwings.
|
||||
-- @extends Core.Fsm#FSM
|
||||
-- @field #table missionqueue Mission queue.
|
||||
-- @extends Ops.Intelligence#INTEL
|
||||
|
||||
--- Be surprised!
|
||||
--
|
||||
@@ -35,22 +36,21 @@ WINGCOMMANDER = {
|
||||
Debug = nil,
|
||||
lid = nil,
|
||||
airwings = {},
|
||||
missionqueue = {},
|
||||
}
|
||||
|
||||
--- Mission capability.
|
||||
-- @type WINGCOMMANDER.Capability
|
||||
-- @field #string missiontype Mission Type.
|
||||
-- @field #number Ntot Total number of assets for this task.
|
||||
-- @field #number Navail Number of available assets
|
||||
-- @field #number Nonmission Number of assets currently on mission.
|
||||
|
||||
--- Mission resources.
|
||||
-- @type WINGCOMMANDER.Recourses
|
||||
--
|
||||
-- @field #string missiontype Mission Type.
|
||||
-- @field #number Ntot Total number of assets for this task.
|
||||
-- @field #number Navail Number of available assets
|
||||
-- @field #number Nonmission Number of assets currently on mission.
|
||||
|
||||
--- Contact details.
|
||||
-- @type WINGCOMMANDER.Contact
|
||||
-- @field Ops.Auftrag#AUFTRAG mission The assigned mission.
|
||||
-- @extends Ops.Intelligence#INTEL.DetectedItem
|
||||
|
||||
--- WINGCOMMANDER class version.
|
||||
-- @field #string version
|
||||
@@ -84,9 +84,7 @@ function WINGCOMMANDER:New(AgentSet)
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
|
||||
|
||||
self:AddTransition("*", "Sitrep", "*") -- WINGCOMMANDER status update
|
||||
--self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
|
||||
|
||||
|
||||
------------------------
|
||||
@@ -110,12 +108,12 @@ function WINGCOMMANDER:New(AgentSet)
|
||||
-- @param #WINGCOMMANDER self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- Triggers the FSM event "FlightStatus".
|
||||
-- @function [parent=#WINGCOMMANDER] WingCommanderStatus
|
||||
--- Triggers the FSM event "Status".
|
||||
-- @function [parent=#WINGCOMMANDER] Status
|
||||
-- @param #WINGCOMMANDER self
|
||||
|
||||
--- Triggers the FSM event "SkipperStatus" after a delay.
|
||||
-- @function [parent=#WINGCOMMANDER] __WingCommanderStatus
|
||||
-- @function [parent=#WINGCOMMANDER] __Status
|
||||
-- @param #WINGCOMMANDER self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
@@ -167,8 +165,10 @@ function WINGCOMMANDER:onafterStart(From, Event, To)
|
||||
local text=string.format("Starting Wing Commander")
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Start the status monitoring.
|
||||
self:__SitRep(-1)
|
||||
-- Start parent INTEL.
|
||||
self:GetParent(self).onafterStart(self, From, Event, To)
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- On after "Sitrep" event.
|
||||
@@ -177,18 +177,19 @@ end
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function WINGCOMMANDER:onafterSitrep(From, Event, To)
|
||||
function WINGCOMMANDER:onafterStatus(From, Event, To)
|
||||
|
||||
-- Start parent INTEL.
|
||||
self:GetParent(self).onafterStatus(self, From, Event, To)
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("No activities")
|
||||
|
||||
|
||||
local capabilities=self:CheckResources()
|
||||
--local capabilities=self:CheckResources()
|
||||
|
||||
-- Number of assets total, on mission, available
|
||||
-- Number of assets available of each mission type.
|
||||
@@ -196,10 +197,25 @@ function WINGCOMMANDER:onafterSitrep(From, Event, To)
|
||||
|
||||
self:I(self.lid..text)
|
||||
|
||||
if DetectedGroupsUnknown then
|
||||
|
||||
for _,_group in pairs(DetectedGroupsUnknown) do
|
||||
local group=_group --Wrapper.Group#GROUP
|
||||
-- Clean up missions where the contact was lost.
|
||||
for _,_contact in pairs(self.ContactsLost) do
|
||||
local contact=_contact --#WINGCOMMANDER.Contact
|
||||
|
||||
if contact.mission and contact.mission.airwing then
|
||||
|
||||
-- Cancel this mission.
|
||||
contact.mission.airwing:MissionCancel(contact.mission)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Create missions for all new contacts.
|
||||
for _,_contact in pairs(self.ContactsUnknown) do
|
||||
local contact=_contact --#WINGCOMMANDER.Contact
|
||||
local group=contact.group --Wrapper.Group#GROUP
|
||||
|
||||
if group and group:IsAlive() then
|
||||
|
||||
@@ -207,14 +223,11 @@ function WINGCOMMANDER:onafterSitrep(From, Event, To)
|
||||
local attribute=group:GetAttribute()
|
||||
local threatlevel=group:GetThreatLevel()
|
||||
|
||||
if category==Group.Category.AIRPLANE or category==Group.Category.HELICOPTER then
|
||||
local mission=nil --Ops.Auftrag#AUFTRAG
|
||||
|
||||
if capability.INTERCEPT.Navail>0 then
|
||||
|
||||
--TODO: Something like get closest AIRWING or squadron?
|
||||
-- Launch even from multiple airwings? Currently Navail is like this.
|
||||
|
||||
end
|
||||
if category==Group.Category.AIRPLANE or category==Group.Category.HELICOPTER then
|
||||
|
||||
mission=AUFTRAG:NewINTERCEPT(group)
|
||||
|
||||
elseif category==Group.Category.GROUND then
|
||||
|
||||
@@ -231,27 +244,113 @@ function WINGCOMMANDER:onafterSitrep(From, Event, To)
|
||||
|
||||
end
|
||||
|
||||
mission=AUFTRAG:NewBAI(group)
|
||||
|
||||
|
||||
elseif category==Group.Category.SHIP then
|
||||
|
||||
--TODO: ANTISHIP
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
-- Add mission to queue.
|
||||
if mission then
|
||||
table.insert(self.missionqueue, mission)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
-- Check mission queue and assign one PLANNED mission.
|
||||
self:CheckMissionQueue()
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Resources
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Check mission queue and assign ONE planned mission.
|
||||
-- @param #WINGCOMMANDER self
|
||||
function WINGCOMMANDER:CheckMissionQueue()
|
||||
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
-- We look for PLANNED missions.
|
||||
if mission.status==AUFTRAG.Status.PLANNED then
|
||||
|
||||
---
|
||||
-- PLANNNED Mission
|
||||
---
|
||||
|
||||
-- Table of airwings that can do the mission.
|
||||
local airwings={}
|
||||
|
||||
-- Loop over all airwings.
|
||||
for _,_airwing in pairs(self.airwings) do
|
||||
local airwing=_airwing --Ops.AirWing#AIRWING
|
||||
|
||||
-- Check if airwing can do this mission.
|
||||
local can,assets=airwing:CanMission(mission.type, mission.nassets)
|
||||
|
||||
-- Can it?
|
||||
if can then
|
||||
|
||||
-- Get coordinate of the target.
|
||||
local coord=mission:GetTargetCoordinate()
|
||||
|
||||
if coord then
|
||||
|
||||
-- Distance from airwing to target.
|
||||
local dist=coord:Get2DDistance(airwing:GetCoordinate())
|
||||
|
||||
-- Add airwing to table of airwings that can.
|
||||
table.insert(airwings, {airwing=airwing, dist=dist, targetcoord=coord})
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Can anyone?
|
||||
if #airwings>0 then
|
||||
|
||||
-- Sort table wrt distace
|
||||
local function sortdist(a,b)
|
||||
return a.dist<b.dist
|
||||
end
|
||||
table.sort(airwings, sortdist)
|
||||
|
||||
local airwing=airwings[1].airwing --Ops.AirWing#AIRWING
|
||||
local targetcoord=airwings[1].targetcoord --Core.Point#COORDINATE
|
||||
|
||||
-- Get waypoint coordinate. This is where the mission is actually executed.
|
||||
local WaypointCoordinate=airwing:GetCoordinate():GetIntermediateCoordinate(targetcoord, 0.5)
|
||||
|
||||
-- Add mission to airwing.
|
||||
airwing:AddMission(mission, Nassets, WaypointCoordinate)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
---
|
||||
-- Missions NOT in PLANNED state
|
||||
---
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Check resources.
|
||||
-- @param #WINGCOMMANDER self
|
||||
-- @return #table
|
||||
@@ -266,10 +365,10 @@ function WINGCOMMANDER:CheckResources()
|
||||
local airwing=_airwing --Ops.AirWing#AIRWING
|
||||
|
||||
-- Get Number of assets that can do this type of missions.
|
||||
local _,nassets=airwing:CanMission(MissionType)
|
||||
local _,assets=airwing:CanMission(MissionType)
|
||||
|
||||
-- Add up airwing resources.
|
||||
capabilities[MissionType]=capabilities[MissionType]+nassets
|
||||
capabilities[MissionType]=capabilities[MissionType]+#assets
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user