This commit is contained in:
Sven Van de Velde 2016-08-03 11:41:52 +02:00
parent 0a5d2a38c5
commit 2d17825268
3 changed files with 529 additions and 182 deletions

View File

@ -1,17 +1,227 @@
--- CARGO Classes
-- @module CARGO
--- This module contains the CARGO classes.
--
-- ===
--
-- 1) @{Cargo#CARGO_BASE} class, extends @{Base#BASE}
-- ==================================================
-- The @{#CARGO_BASE} class defines the core functions that defines a cargo object within MOOSE.
-- A cargo is a logical object defined within a @{Mission}, that is available for transport, and has a life status within a simulation.
--
-- Cargo can be of various forms:
--
-- * CARGO_UNIT, represented by a @{Unit} in a @{Group}: Cargo can be represented by a Unit in a Group. Destruction of the Unit will mean that the cargo is lost.
-- * CARGO_STATIC, represented by a @{Static}: Cargo can be represented by a Static. Destruction of the Static will mean that the cargo is lost.
-- * CARGO_PACKAGE, contained in a @{Unit} of a @{Group}: Cargo can be contained within a Unit of a Group. The cargo can be **delivered** by the @{Unit}. If the Unit is destroyed, the cargo will be destroyed also.
-- * CARGO_PACKAGE, Contained in a @{Static}: Cargo can be contained within a Static. The cargo can be **collected** from the @Static. If the @{Static} is destroyed, the cargo will be destroyed.
-- * CARGO_SLINGLOAD, represented by a @{Cargo} that is transportable: Cargo can be represented by a Cargo object that is transportable. Destruction of the Cargo will mean that the cargo is lost.
--
-- @module Cargo
--- Clients are those Groups defined within the Mission Editor that have the skillset defined as "Client" or "Player".
-- These clients are defined within the Mission Orchestration Framework (MOF)
CARGOS = {}
--- @type CARGO
-- @field #string Type A string defining the type of the cargo. eg. Engineers, Equipment, Screwdrivers.
-- @field #string Name A string defining the name of the cargo. The name is the unique identifier of the cargo.
-- @field #number Weight A number defining the weight of the cargo. The weight is expressed in kg.
-- @field #number ReportRadius (optional) A number defining the radius in meters when the cargo is signalling or reporting to a Carrier.
-- @field #number NearRadius (optional) A number defining the radius in meters when the cargo is near to a Carrier, so that it can be loaded.
-- @field Positionable#POSITIONABLE CargoObject The alive DCS object representing the cargo. This value can be nil, meaning, that the cargo is not represented anywhere...
-- @field Positionable#POSITIONABLE CargoCarrier The alive DCS object carrying the cargo. This value can be nil, meaning, that the cargo is not contained anywhere...
-- @field #boolean Slingloadable This flag defines if the cargo can be slingloaded.
-- @field #boolean Moveable This flag defines if the cargo is moveable.
-- @field #boolean Representable This flag defines if the cargo can be represented by a DCS Unit.
-- @field #boolean Containable This flag defines if the cargo can be contained within a DCS Unit.
CARGO = {
ClassName = "CARGO",
STATUS = {
NONE = 0,
LOADED = 1,
UNLOADED = 2,
LOADING = 3
},
Type = nil,
Name = nil,
Weight = nil,
CargoObject = nil,
CargoCarrier = nil,
Representable = false,
Slingloadable = false,
Moveable = false,
Containable = false,
}
--- Add Cargo to the mission...
function CARGO:New( Mission, Type, Name, Weight, ReportRadius, NearRadius ) local self = BASE:Inherit( self, BASE:New() ) -- #CARGO
self:F( { Type, Name, Weight, ReportRadius, NearRadius } )
self.Type = Type
self.Name = Name
self.Weight = Weight
self.ReportRadius = ReportRadius
self.NearRadius = NearRadius
self.CargoObject = nil
self.CargoCarrier = nil
self.Representable = false
self.Slingloadable = false
self.Moveable = false
self.Containable = false
self:StatusNone()
return self
end
function CARGO:Spawn( PointVec2 )
self:F()
return self
end
function CARGO:Load( CargoObject, CargoCarrier )
self:F()
self:StatusLoaded( CargoCarrier )
return self
end
function CARGO:UnLoad( CargoCarrier, CargoObject )
self:F()
self:StatusUnLoaded( CargoObject )
return self
end
function CARGO:OnBoard( CargoObject, CargoCarrier )
self:F()
end
function CARGO:OnBoarded( CargoCarrier )
self:F()
local OnBoarded = false
return OnBoarded
end
function CARGO:IsNear( CargoCarrier, CargoObject, Radius )
self:F()
local Near = true
return Near
end
function CARGO:IsLoading()
self:F()
if self:IsStatusLoading() then
return self.Object
end
return nil
end
function CARGO:IsContained()
self:F()
if self:IsStatusContained() then
return self.Object
end
return nil
end
function CARGO:IsLandingRequired()
self:F()
return true
end
function CARGO:IsSlingLoad()
self:F()
return false
end
function CARGO:StatusNone()
self:F()
self.CargoClient = nil
self.CargoStatus = CARGO.STATUS.NONE
return self
end
function CARGO:StatusLoading( Carrier )
self:F()
self.CargoClient = Carrier
self.CargoStatus = CARGO.STATUS.LOADING
self:T( "Cargo " .. self.CargoName .. " loading to Client: " .. self.CargoClient:GetClientGroupName() )
return self
end
function CARGO:StatusLoaded( Client )
self:F()
self.CargoClient = Client
self.CargoStatus = CARGO.STATUS.LOADED
self:T( "Cargo " .. self.CargoName .. " loaded in Client: " .. self.CargoClient:GetClientGroupName() )
return self
end
function CARGO:StatusUnLoaded()
self:F()
self.CargoClient = nil
self.CargoStatus = CARGO.STATUS.UNLOADED
return self
end
function CARGO:IsStatusNone()
self:F()
return self.CargoStatus == CARGO.STATUS.NONE
end
function CARGO:IsStatusLoading()
self:F()
return self.CargoStatus == CARGO.STATUS.LOADING
end
function CARGO:IsStatusLoaded()
self:F()
return self.CargoStatus == CARGO.STATUS.LOADED
end
function CARGO:IsStatusUnLoaded()
self:F()
return self.CargoStatus == CARGO.STATUS.UNLOADED
end
CARGO_ZONE = {
ClassName="CARGO_ZONE",
@ -326,180 +536,7 @@ function CARGO_ZONE:GetCargoZoneName()
return self.CargoZoneName
end
CARGO = {
ClassName = "CARGO",
STATUS = {
NONE = 0,
LOADED = 1,
UNLOADED = 2,
LOADING = 3
},
CargoClient = nil
}
--- Add Cargo to the mission... Cargo functionality needs to be reworked a bit, so this is still under construction. I need to make a CARGO Class...
function CARGO:New( CargoType, CargoName, CargoWeight ) local self = BASE:Inherit( self, BASE:New() )
self:F( { CargoType, CargoName, CargoWeight } )
self.CargoType = CargoType
self.CargoName = CargoName
self.CargoWeight = CargoWeight
self:StatusNone()
return self
end
function CARGO:Spawn( Client )
self:F()
return self
end
function CARGO:IsNear( Client, LandingZone )
self:F()
local Near = true
return Near
end
function CARGO:IsLoadingToClient()
self:F()
if self:IsStatusLoading() then
return self.CargoClient
end
return nil
end
function CARGO:IsLoadedInClient()
self:F()
if self:IsStatusLoaded() then
return self.CargoClient
end
return nil
end
function CARGO:UnLoad( Client, TargetZoneName )
self:F()
self:StatusUnLoaded()
return self
end
function CARGO:OnBoard( Client, LandingZone )
self:F()
local Valid = true
self.CargoClient = Client
local ClientUnit = Client:GetClientGroupDCSUnit()
return Valid
end
function CARGO:OnBoarded( Client, LandingZone )
self:F()
local OnBoarded = true
return OnBoarded
end
function CARGO:Load( Client )
self:F()
self:StatusLoaded( Client )
return self
end
function CARGO:IsLandingRequired()
self:F()
return true
end
function CARGO:IsSlingLoad()
self:F()
return false
end
function CARGO:StatusNone()
self:F()
self.CargoClient = nil
self.CargoStatus = CARGO.STATUS.NONE
return self
end
function CARGO:StatusLoading( Client )
self:F()
self.CargoClient = Client
self.CargoStatus = CARGO.STATUS.LOADING
self:T( "Cargo " .. self.CargoName .. " loading to Client: " .. self.CargoClient:GetClientGroupName() )
return self
end
function CARGO:StatusLoaded( Client )
self:F()
self.CargoClient = Client
self.CargoStatus = CARGO.STATUS.LOADED
self:T( "Cargo " .. self.CargoName .. " loaded in Client: " .. self.CargoClient:GetClientGroupName() )
return self
end
function CARGO:StatusUnLoaded()
self:F()
self.CargoClient = nil
self.CargoStatus = CARGO.STATUS.UNLOADED
return self
end
function CARGO:IsStatusNone()
self:F()
return self.CargoStatus == CARGO.STATUS.NONE
end
function CARGO:IsStatusLoading()
self:F()
return self.CargoStatus == CARGO.STATUS.LOADING
end
function CARGO:IsStatusLoaded()
self:F()
return self.CargoStatus == CARGO.STATUS.LOADED
end
function CARGO:IsStatusUnLoaded()
self:F()
return self.CargoStatus == CARGO.STATUS.UNLOADED
end
CARGO_GROUP = {

View File

@ -0,0 +1,173 @@
--- @module Process_Pickup
--- PROCESS_PICKUP class
-- @type PROCESS_PICKUP
-- @field Unit#UNIT ProcessUnit
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Process#PROCESS
PROCESS_PICKUP = {
ClassName = "PROCESS_PICKUP",
Fsm = {},
TargetSetUnit = nil,
}
--- Creates a new DESTROY process.
-- @param #PROCESS_PICKUP self
-- @param Task#TASK Task
-- @param Unit#UNIT ProcessUnit
-- @param Set#SET_UNIT TargetSetUnit
-- @return #PROCESS_PICKUP self
function PROCESS_PICKUP:New( Task, ProcessName, ProcessUnit )
-- Inherits from BASE
local self = BASE:Inherit( self, PROCESS:New( ProcessName, Task, ProcessUnit ) ) -- #PROCESS_PICKUP
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
self.DisplayCategory = "HQ" -- Targets is the default display category
self.Fsm = STATEMACHINE_PROCESS:New( self, {
initial = 'Assigned',
events = {
{ name = 'Start', from = 'Assigned', to = 'Navigating' },
{ name = 'Start', from = 'Navigating', to = 'Navigating' },
{ name = 'Nearby', from = 'Navigating', to = 'Preparing' },
{ name = 'Pickup', from = 'Preparing', to = 'Loading' },
{ name = 'Load', from = 'Loading', to = 'Success' },
{ name = 'Fail', from = 'Assigned', to = 'Failed' },
{ name = 'Fail', from = 'Navigating', to = 'Failed' },
{ name = 'Fail', from = 'Preparing', to = 'Failed' },
},
callbacks = {
onStart = self.OnStart,
onNearby = self.OnNearby,
onPickup = self.OnPickup,
onLoad = self.OnLoad,
},
endstates = { 'Success', 'Failed' }
} )
return self
end
--- Process Events
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_PICKUP:OnStart( Fsm, Event, From, To )
self:NextEvent( Fsm.Start )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_PICKUP:OnNavigating( Fsm, Event, From, To )
local TaskGroup = self.ProcessUnit:GetGroup()
if self.DisplayCount >= self.DisplayInterval then
MESSAGE:New( "Your group with assigned " .. self.Task:GetName() .. " task has " .. self.TargetSetUnit:GetUnitTypesText() .. " targets left to be destroyed.", 5, "HQ" ):ToGroup( TaskGroup )
self.DisplayCount = 1
else
self.DisplayCount = self.DisplayCount + 1
end
return true -- Process always the event.
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA Event
function PROCESS_PICKUP:OnHitTarget( Fsm, Event, From, To, Event )
self.TargetSetUnit:Flush()
if self.TargetSetUnit:FindUnit( Event.IniUnitName ) then
self.TargetSetUnit:RemoveUnitsByName( Event.IniUnitName )
local TaskGroup = self.ProcessUnit:GetGroup()
MESSAGE:New( "You hit a target. Your group with assigned " .. self.Task:GetName() .. " task has " .. self.TargetSetUnit:Count() .. " targets ( " .. self.TargetSetUnit:GetUnitTypesText() .. " ) left to be destroyed.", 15, "HQ" ):ToGroup( TaskGroup )
end
if self.TargetSetUnit:Count() > 0 then
self:NextEvent( Fsm.MoreTargets )
else
self:NextEvent( Fsm.Destroyed )
end
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_PICKUP:OnMoreTargets( Fsm, Event, From, To )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA DCSEvent
function PROCESS_PICKUP:OnKilled( Fsm, Event, From, To )
self:NextEvent( Fsm.Restart )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_PICKUP:OnRestart( Fsm, Event, From, To )
self:NextEvent( Fsm.Menu )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_PICKUP:OnDestroyed( Fsm, Event, From, To )
end
--- DCS Events
--- @param #PROCESS_PICKUP self
-- @param Event#EVENTDATA Event
function PROCESS_PICKUP:EventDead( Event )
if Event.IniDCSUnit then
self:NextEvent( self.Fsm.HitTarget, Event )
end
end

View File

@ -0,0 +1,137 @@
--- This module contains the TASK_PICKUP classes.
--
-- 1) @{#TASK_PICKUP} class, extends @{Task#TASK_BASE}
-- ===================================================
-- The @{#TASK_PICKUP} class defines a pickup task of a @{Set} of @{CARGO} objects defined within the mission.
-- based on the tasking capabilities defined in @{Task#TASK_BASE}.
-- The TASK_PICKUP is implemented using a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses:
--
-- * **None**: Start of the process
-- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Assign#PROCESS_ASSIGN_ACCEPT} is started to accept the task.
-- * **Assigned**: The SEAD task is assigned to a @{Group#GROUP}. Upon Assigned, the sub-process @{Process_Route#PROCESS_ROUTE} is started to route the active Units in the Group to the attack zone.
-- * **Success**: The SEAD task is successfully completed. Upon Success, the sub-process @{Process_SEAD#PROCESS_SEAD} is started to follow-up successful SEADing of the targets assigned in the task.
-- * **Failed**: The SEAD task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
--
-- ===
--
-- ### Authors: FlightControl - Design and Programming
--
-- @module Task_PICKUP
do -- TASK_PICKUP
--- The TASK_PICKUP class
-- @type TASK_PICKUP
-- @extends Task#TASK_BASE
TASK_PICKUP = {
ClassName = "TASK_PICKUP",
}
--- Instantiates a new TASK_PICKUP.
-- @param #TASK_PICKUP self
-- @param Mission#MISSION Mission
-- @param Set#SET_GROUP AssignedSetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param #string TaskType BAI or CAS
-- @param Set#SET_UNIT UnitSetTargets
-- @param Zone#ZONE_BASE TargetZone
-- @return #TASK_PICKUP self
function TASK_PICKUP:New( Mission, AssignedSetGroup, TaskName, TaskType )
local self = BASE:Inherit( self, TASK_BASE:New( Mission, AssignedSetGroup, TaskName, TaskType, "PICKUP" ) )
self:F()
_EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self )
_EVENTDISPATCHER:OnDead( self._EventDead, self )
_EVENTDISPATCHER:OnCrash( self._EventDead, self )
_EVENTDISPATCHER:OnPilotDead( self._EventDead, self )
return self
end
--- Removes a TASK_PICKUP.
-- @param #TASK_PICKUP self
-- @return #nil
function TASK_PICKUP:CleanUp()
self:GetParent( self ):CleanUp()
return nil
end
--- Assign the @{Task} to a @{Unit}.
-- @param #TASK_PICKUP self
-- @param Unit#UNIT TaskUnit
-- @return #TASK_PICKUP self
function TASK_PICKUP:AssignToUnit( TaskUnit )
self:F( TaskUnit:GetName() )
local ProcessAssign = self:AddProcess( TaskUnit, PROCESS_ASSIGN_ACCEPT:New( self, TaskUnit, self.TaskBriefing ) )
local ProcessPickup = self:AddProcess( TaskUnit, PROCESS_PICKUP:New( self, self.TaskType, TaskUnit ) )
local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, TaskUnit, {
initial = 'None',
events = {
{ name = 'Next', from = 'None', to = 'Planned' },
{ name = 'Next', from = 'Planned', to = 'Assigned' },
{ name = 'Next', from = 'Assigned', to = 'Success' },
{ name = 'Fail', from = 'Assigned', to = 'Failed' },
},
callbacks = {
onNext = self.OnNext,
},
subs = {
Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } },
Pickup = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessDestroy.Fsm, event = 'Start', returnevents = { 'Next' } },
}
} ) )
ProcessRoute:AddScore( "Failed", "failed to destroy a ground unit", -100 )
ProcessDestroy:AddScore( "Pickup", "Picked-Up a Cargo", 25 )
ProcessDestroy:AddScore( "Failed", "failed to destroy a ground unit", -100 )
Process:Next()
return self
end
--- StateMachine callback function for a TASK
-- @param #TASK_PICKUP self
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA Event
function TASK_PICKUP:OnNext( Fsm, Event, From, To, Event )
self:SetState( self, "State", To )
end
--- @param #TASK_PICKUP self
function TASK_PICKUP:GetPlannedMenuText()
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
end
--- @param #TASK_PICKUP self
function TASK_PICKUP:_Schedule()
self:F2()
self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 )
return self
end
--- @param #TASK_PICKUP self
function TASK_PICKUP._Scheduler()
self:F2()
return true
end
end