diff --git a/Moose Development/Moose/Cargo.lua b/Moose Development/Moose/Cargo.lua index 314706d99..158494e9b 100644 --- a/Moose Development/Moose/Cargo.lua +++ b/Moose Development/Moose/Cargo.lua @@ -38,12 +38,6 @@ do -- CARGO -- @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, @@ -55,191 +49,167 @@ do -- CARGO Containable = false, } ---- @type CARGO.CargoObjects --- @map < #string, Positionable#POSITIONABLE > The alive POSITIONABLE objects representing the the cargo. - - ---- CARGO Constructor. --- @param #CARGO self --- @param Mission#MISSION Mission --- @param #string Type --- @param #string Name --- @param #number Weight --- @param #number ReportRadius (optional) --- @param #number NearRadius (optional) --- @return #CARGO -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.CargoObjects = nil - self.CargoCarrier = nil - self.Representable = false - self.Slingloadable = false - self.Moveable = false - self.Containable = false - - self:StatusNone() + --- @type CARGO.CargoObjects + -- @map < #string, Positionable#POSITIONABLE > The alive POSITIONABLE objects representing the the cargo. - CARGOS[self.CargoName] = self - - return self -end - ---- Template method to spawn a new representation of the CARGO in the simulator. --- @param #CARGO self --- @return #CARGO -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( 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 + + --- CARGO Constructor. + -- @param #CARGO self + -- @param Mission#MISSION Mission + -- @param #string Type + -- @param #string Name + -- @param #number Weight + -- @param #number ReportRadius (optional) + -- @param #number NearRadius (optional) + -- @return #CARGO + 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.CargoObjects = nil + self.CargoCarrier = nil + self.Representable = false + self.Slingloadable = false + self.Moveable = false + self.Containable = false + + local Process = STATEMACHINE_PROCESS:New( self, { + initial = 'UnLoaded', + events = { + { name = 'Board', from = 'UnLoaded', to = 'Boarding' }, + { name = 'Boarded', from = 'Boarding', to = 'Boarding' }, + { name = 'Load', from = 'Boarding', to = 'Loaded' }, + { name = 'Load', from = 'UnLoaded', to = 'Loaded' }, + { name = 'UnBoard', from = 'Loaded', to = 'UnBoarding' }, + { name = 'UnBoard', from = 'UnBoarding', to = 'UnBoarding' }, + { name = 'UnBoarded', from = 'UnBoarding', to = 'UnLoaded' }, + { name = 'UnLoad', from = 'Loaded', to = 'UnLoaded' }, + }, + callbacks = { + OnBoard = self.Board, + OnBoarded = self.OnBoarded, + OnLoad = self.Load, + OnUnBoard = self.UnBoard, + OnUnBoarded = self.UnBoarded, + OnUnLoad = self.UnLoad, + OnLoaded = self.Loaded, + OnUnLoaded = self.UnLoaded, + }, + } ) + + self.CargoScheduler = SCHEDULER:New() + + CARGOS[self.CargoName] = self + + return self + end + + --- @param #CARGO self + function CARGO:NextEvent( NextEvent, ... ) + self:F( self.Name ) + self.CargoScheduler:Schedule( self.Fsm, NextEvent, arg, 1 ) -- This schedules the next event, but only if scheduling is activated. end - return nil -end - - -function CARGO:IsContained() - self:F() - - if self:IsStatusContained() then - return self.Object + --- Template method to spawn a new representation of the CARGO in the simulator. + -- @param #CARGO self + -- @return #CARGO + function CARGO:Spawn( PointVec2 ) + self:F() + + end + + --- Load Event. + -- @param #CARGO self + -- @param StateMachine#STATEMACHINE_PROCESS FsmP + -- @param #string Event + -- @param #string From + -- @param #string To + -- @param Unit#UNIT CargoCarrier + function CARGO:Load( FsmP, Event, From, To, CargoCarrier ) + self:F() + end - return nil -end + --- UnLoad Event. + -- @param #CARGO self + -- @param StateMachine#STATEMACHINE_PROCESS FsmP + -- @param #string Event + -- @param #string From + -- @param #string To + function CARGO:UnLoad( FsmP, Event, From, To ) + self:F() + + end + + --- Board Event. + -- @param #CARGO self + -- @param StateMachine#STATEMACHINE_PROCESS FsmP + -- @param #string Event + -- @param #string From + -- @param #string To + -- @param Unit#UNIT CargoCarrier + function CARGO:Board( FsmP, Event, From, To, CargoCarrier ) + self:F() + + end + + --- Boarded Event. + -- @param #CARGO self + -- @param StateMachine#STATEMACHINE_PROCESS FsmP + -- @param #string Event + -- @param #string From + -- @param #string To + -- @param Unit#UNIT CargoCarrier + function CARGO:Boarded( FsmP, Event, From, To, CargoCarrier ) + self:F() + + end -function CARGO:IsLandingRequired() - self:F() - return true -end - -function CARGO:IsSlingLoad() - self:F() - return false -end + function CARGO:IsNear( CargoCarrier, CargoObject, Radius ) + self:F() + + local Near = true + + return Near + + end -function CARGO:StatusNone() - self:F() + --- Loaded State. + -- @param #CARGO self + -- @param StateMachine#STATEMACHINE_PROCESS FsmP + -- @param #string Event + -- @param #string From + -- @param #string To + -- @param Unit#UNIT CargoCarrier + function CARGO:Loaded( FsmP, Event, From, To, CargoCarrier ) + self:F() + + self.CargoCarrier = CargoCarrier + self:T( "Cargo " .. self.Name .. " loaded in " .. self.CargoCarrier:GetName() ) + end - 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 + --- UnLoaded State. + -- @param #CARGO self + -- @param StateMachine#STATEMACHINE_PROCESS FsmP + -- @param #string Event + -- @param #string From + -- @param #string To + function CARGO:StatusUnLoaded( FsmP, Event, From, To ) + self:F() + + self:T( "Cargo " .. self.Name .. " unloaded from " .. self.CargoCarrier:GetName() ) + self.CargoCarrier = nil + end end @@ -270,14 +240,16 @@ do -- CARGO_REPRESENTABLE return self end - --- Onboard representable Cargo to a Carrier. + --- Board Event. -- @param #CARGO_REPRESENTABLE self - -- @param Unit#UNIT Carrier - function CARGO_REPRESENTABLE:Onboard( Carrier ) + -- @param StateMachine#STATEMACHINE_PROCESS FsmP + -- @param #string Event + -- @param #string From + -- @param #string To + -- @param Unit#UNIT CargoCarrier + function CARGO_REPRESENTABLE:Onboard( FsmP, Event, From, To, CargoCarrier ) self:F() - local OnBoardScheduler = SCHEDULER:New( self, self.ExecuteOnboarding, 1, 1, 0, 30 ) - self.CargoInAir = self.CargoObject:InAir() self:T( self.CargoInAir ) @@ -298,26 +270,40 @@ do -- CARGO_REPRESENTABLE local TaskRoute = self.CargoObject:TaskRoute( Points ) self.CargoObject:SetTask( TaskRoute, 4 ) end - - self:StatusLoading( Carrier ) - end - - --- Can the Cargo Onboard to the Carrier? - -- @param #CARGO_REPRESENTABLE self - -- @return #boolean true if Cargo is near enough to be Onboarded. - function CARGO_REPRESENTABLE:CanOnboard( Carrier ) - return self:IsNear( Carrier ) - end - --- Execute the Cargo Onboarding to the Carrier. - -- @param #CARGO_REPRESENTABLE self - function CARGO_REPRESENTABLE:ExecuteOnboarding( Carrier ) - if self:CanOnboard( Carrier ) then - self.CargoCarrier = Carrier - self.CargoObject:Destroy() - return false + self:NextEvent( FsmP.Boarded, CargoCarrier ) + + end + + --- Boarded Event. + -- @param #CARGO self + -- @param StateMachine#STATEMACHINE_PROCESS FsmP + -- @param #string Event + -- @param #string From + -- @param #string To + -- @param Unit#UNIT CargoCarrier + function CARGO:Boarded( FsmP, Event, From, To, CargoCarrier ) + self:F() + + if self:IsNear( CargoCarrier ) then + self:NextEvent( FsmP.Boarded, CargoCarrier ) + else + self:NextEvent( FsmP.Load, CargoCarrier ) end - return true + end + + --- Load Event. + -- @param #CARGO self + -- @param StateMachine#STATEMACHINE_PROCESS FsmP + -- @param #string Event + -- @param #string From + -- @param #string To + -- @param Unit#UNIT CargoCarrier + function CARGO:Load( FsmP, Event, From, To, CargoCarrier ) + self:F() + + self.CargoCarrier = CargoCarrier + self.CargoObject:Destroy() end end @@ -349,244 +335,6 @@ do -- CARGO_UNIT end -do -- CARGO_GROUP - - --- @type CARGO_GROUP - CARGO_GROUP = { - ClassName = "CARGO_GROUP" - } - ---- CARGO_GROUP Constructor. --- @param #CARGO_GROUP self --- @param Mission#MISSION Mission --- @param Group#GROUP CargoGroup --- @param #string Type --- @param #string Name --- @param #number Weight --- @param #number ReportRadius (optional) --- @param #number NearRadius (optional) --- @return #CARGO_GROUP -function CARGO_GROUP:New( Mission, CargoGroup, Type, Name, Weight, ReportRadius, NearRadius ) - local self = BASE:Inherit( self, CARGO:New( Mission, CargoGroup, Type, Name, Weight, ReportRadius, NearRadius ) ) -- #CARGO - self:F( { Type, Name, Weight, ReportRadius, NearRadius } ) - - self.CargoSpawn = SPAWN:NewWithAlias( CargoGroupTemplate, CargoName ) - self.CargoZone = CargoZone - - CARGOS[self.CargoName] = self - - return self - -end - -function CARGO_GROUP:Spawn( Client ) - self:F( { Client } ) - - local SpawnCargo = true - - if self:IsStatusNone() then - local CargoGroup = Group.getByName( self.CargoName ) - if CargoGroup and CargoGroup:isExist() then - SpawnCargo = false - end - - elseif self:IsStatusLoading() then - - local Client = self:IsLoadingToClient() - if Client and Client:GetDCSGroup() then - SpawnCargo = false - else - local CargoGroup = Group.getByName( self.CargoName ) - if CargoGroup and CargoGroup:isExist() then - SpawnCargo = false - end - end - - elseif self:IsStatusLoaded() then - - local ClientLoaded = self:IsLoadedInClient() - -- Now test if another Client is alive (not this one), and it has the CARGO, then this cargo does not need to be initialized and spawned. - if ClientLoaded and ClientLoaded ~= Client then - local ClientGroup = Client:GetDCSGroup() - if ClientLoaded:GetClientGroupDCSUnit() and ClientLoaded:GetClientGroupDCSUnit():isExist() then - SpawnCargo = false - else - self:StatusNone() - end - else - -- Same Client, but now in initialize, so set back the status to None. - self:StatusNone() - end - - elseif self:IsStatusUnLoaded() then - - SpawnCargo = false - - end - - if SpawnCargo then - if self.CargoZone:GetCargoHostUnit() then - --- ReSpawn the Cargo from the CargoHost - self.CargoGroupName = self.CargoSpawn:SpawnFromUnit( self.CargoZone:GetCargoHostUnit(), 60, 30, 1 ):GetName() - else - --- ReSpawn the Cargo in the CargoZone without a host ... - self:T( self.CargoZone ) - self.CargoGroupName = self.CargoSpawn:SpawnInZone( self.CargoZone, true, 1 ):GetName() - end - self:StatusNone() - end - - self:T( { self.CargoGroupName, CARGOS[self.CargoName].CargoGroupName } ) - - return self -end - -function CARGO_GROUP:IsNear( Client, LandingZone ) - self:F() - - local Near = false - - if self.CargoGroupName then - local CargoGroup = Group.getByName( self.CargoGroupName ) - if routines.IsPartOfGroupInRadius( CargoGroup, Client:GetPositionVec3(), 250 ) then - Near = true - end - end - - return Near - -end - - -function CARGO_GROUP:OnBoard( Client, LandingZone, OnBoardSide ) - self:F() - - local Valid = true - - local ClientUnit = Client:GetClientGroupDCSUnit() - - local CarrierPos = ClientUnit:getPoint() - local CarrierPosMove = ClientUnit:getPoint() - local CarrierPosOnBoard = ClientUnit:getPoint() - - local CargoGroup = Group.getByName( self.CargoGroupName ) - - local CargoUnit = CargoGroup:getUnit(1) - local CargoPos = CargoUnit:getPoint() - - self.CargoInAir = CargoUnit:inAir() - - self:T( self.CargoInAir ) - - -- Only move the group to the carrier when the cargo is not in the air - -- (eg. cargo can be on a oil derrick, moving the cargo on the oil derrick will drop the cargo on the sea). - if not self.CargoInAir then - - local Points = {} - - self:T( 'CargoPos x = ' .. CargoPos.x .. " z = " .. CargoPos.z ) - self:T( 'CarrierPosMove x = ' .. CarrierPosMove.x .. " z = " .. CarrierPosMove.z ) - - Points[#Points+1] = routines.ground.buildWP( CargoPos, "Cone", 10 ) - - self:T( 'Points[1] x = ' .. Points[1].x .. " y = " .. Points[1].y ) - - if OnBoardSide == nil then - OnBoardSide = CLIENT.ONBOARDSIDE.NONE - end - - if OnBoardSide == CLIENT.ONBOARDSIDE.LEFT then - - self:T( "TransportCargoOnBoard: Onboarding LEFT" ) - CarrierPosMove.z = CarrierPosMove.z - 25 - CarrierPosOnBoard.z = CarrierPosOnBoard.z - 5 - Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 ) - Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 ) - - elseif OnBoardSide == CLIENT.ONBOARDSIDE.RIGHT then - - self:T( "TransportCargoOnBoard: Onboarding RIGHT" ) - CarrierPosMove.z = CarrierPosMove.z + 25 - CarrierPosOnBoard.z = CarrierPosOnBoard.z + 5 - Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 ) - Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 ) - - elseif OnBoardSide == CLIENT.ONBOARDSIDE.BACK then - - self:T( "TransportCargoOnBoard: Onboarding BACK" ) - CarrierPosMove.x = CarrierPosMove.x - 25 - CarrierPosOnBoard.x = CarrierPosOnBoard.x - 5 - Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 ) - Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 ) - - elseif OnBoardSide == CLIENT.ONBOARDSIDE.FRONT then - - self:T( "TransportCargoOnBoard: Onboarding FRONT" ) - CarrierPosMove.x = CarrierPosMove.x + 25 - CarrierPosOnBoard.x = CarrierPosOnBoard.x + 5 - Points[#Points+1] = routines.ground.buildWP( CarrierPosMove, "Cone", 10 ) - Points[#Points+1] = routines.ground.buildWP( CarrierPosOnBoard, "Cone", 10 ) - - elseif OnBoardSide == CLIENT.ONBOARDSIDE.NONE then - - self:T( "TransportCargoOnBoard: Onboarding CENTRAL" ) - Points[#Points+1] = routines.ground.buildWP( CarrierPos, "Cone", 10 ) - - end - self:T( "TransportCargoOnBoard: Routing " .. self.CargoGroupName ) - - --routines.scheduleFunction( routines.goRoute, { self.CargoGroupName, Points}, timer.getTime() + 4 ) - SCHEDULER:New( self, routines.goRoute, { self.CargoGroupName, Points}, 4 ) - end - - self:StatusLoading( Client ) - - return Valid - -end - - -function CARGO_GROUP:OnBoarded( Client, LandingZone ) - self:F() - - local OnBoarded = false - - local CargoGroup = Group.getByName( self.CargoGroupName ) - - if not self.CargoInAir then - if routines.IsPartOfGroupInRadius( CargoGroup, Client:GetPositionVec3(), 25 ) then - CargoGroup:destroy() - self:StatusLoaded( Client ) - OnBoarded = true - end - else - CargoGroup:destroy() - self:StatusLoaded( Client ) - OnBoarded = true - end - - return OnBoarded -end - - -function CARGO_GROUP:UnLoad( Client, TargetZoneName ) - self:F() - - self:T( 'self.CargoName = ' .. self.CargoName ) - - local CargoGroup = self.CargoSpawn:SpawnFromUnit( Client:GetClientGroupUnit(), 60, 30 ) - - self.CargoGroupName = CargoGroup:GetName() - self:T( 'self.CargoGroupName = ' .. self.CargoGroupName ) - - CargoGroup:TaskRouteToZone( ZONE:New( TargetZoneName ), true ) - - self:StatusUnLoaded() - - return self -end - -end CARGO_PACKAGE = { ClassName = "CARGO_PACKAGE" diff --git a/Moose Development/Moose/Object.lua b/Moose Development/Moose/Object.lua index 1a5ac146c..eb546fa22 100644 --- a/Moose Development/Moose/Object.lua +++ b/Moose Development/Moose/Object.lua @@ -68,5 +68,22 @@ function OBJECT:GetID() return nil end +--- Destroys the OBJECT. +-- @param #OBJECT self +-- @return #nil The DCS Unit is not existing or alive. +function UNIT:Destroy() + self:F2( self.ObjectName ) + + local DCSObject = self:GetDCSObject() + + if DCSObject then + + DCSObject:destroy() + end + + return nil +end + + diff --git a/Moose Development/Moose/Unit.lua b/Moose Development/Moose/Unit.lua index 3888939af..05cce20a2 100644 --- a/Moose Development/Moose/Unit.lua +++ b/Moose Development/Moose/Unit.lua @@ -187,22 +187,6 @@ function UNIT:IsActive() return nil end ---- Destroys the @{Unit}. --- @param Unit#UNIT self --- @return #nil The DCS Unit is not existing or alive. -function UNIT:Destroy() - self:F2( self.UnitName ) - - local DCSUnit = self:GetDCSObject() - - if DCSUnit then - - DCSUnit:destroy() - end - - return nil -end - --- Returns the Unit's callsign - the localized string. diff --git a/Moose Test Missions/Moose_Test_CARGO/Moose_Test_CARGO_Pickup/MOOSE_Test_CARGO_Pickup.miz b/Moose Test Missions/Moose_Test_CARGO/Moose_Test_CARGO_Pickup/MOOSE_Test_CARGO_Pickup.miz index a6537ced1..17f824209 100644 Binary files a/Moose Test Missions/Moose_Test_CARGO/Moose_Test_CARGO_Pickup/MOOSE_Test_CARGO_Pickup.miz and b/Moose Test Missions/Moose_Test_CARGO/Moose_Test_CARGO_Pickup/MOOSE_Test_CARGO_Pickup.miz differ