mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Finish Cargo/Limits
This commit is contained in:
commit
4f38d8109d
@ -96,7 +96,7 @@ function AI_CARGO_APC:New( APC, CargoSet, CombatRadius )
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
|
||||
self:AddTransition( "*", "Load", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Board", "Boarding" )
|
||||
self:AddTransition( { "Boarding", "Loaded" }, "Board", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Loaded", "Loaded" )
|
||||
self:AddTransition( "Loaded", "Unload", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
|
||||
@ -139,7 +139,7 @@ function AI_CARGO_APC:New( APC, CargoSet, CombatRadius )
|
||||
-- @function [parent=#AI_CARGO_APC] __Pickup
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param #number Delay
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param Core.Point#COORDINATE Coordinate Pickup place. If not given, loading starts at the current location.
|
||||
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
|
||||
|
||||
--- Deploy Handler OnBefore for AI_CARGO_APC
|
||||
@ -170,8 +170,8 @@ function AI_CARGO_APC:New( APC, CargoSet, CombatRadius )
|
||||
--- Deploy Asynchronous Trigger for AI_CARGO_APC
|
||||
-- @function [parent=#AI_CARGO_APC] __Deploy
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Delay
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
|
||||
|
||||
|
||||
@ -194,8 +194,12 @@ function AI_CARGO_APC:New( APC, CargoSet, CombatRadius )
|
||||
|
||||
self:__Monitor( 1 )
|
||||
|
||||
|
||||
self:SetCarrier( APC )
|
||||
|
||||
for _, APCUnit in pairs( APC:GetUnits() ) do
|
||||
APCUnit:SetCargoBayWeightLimit()
|
||||
end
|
||||
|
||||
self.Transporting = false
|
||||
self.Relocating = false
|
||||
|
||||
@ -411,7 +415,6 @@ function AI_CARGO_APC:onbeforeLoad( APC, From, Event, To )
|
||||
self:F( { APC, From, Event, To } )
|
||||
|
||||
local Boarding = false
|
||||
self.BoardingCount = 0
|
||||
|
||||
if APC and APC:IsAlive() then
|
||||
self.APC_Cargo = {}
|
||||
@ -423,16 +426,25 @@ function AI_CARGO_APC:onbeforeLoad( APC, From, Event, To )
|
||||
if Cargo:IsUnLoaded() and not Cargo:IsDeployed() then
|
||||
if Cargo:IsInLoadRadius( APCUnit:GetCoordinate() ) then
|
||||
self:F( { "In radius", APCUnit:GetName() } )
|
||||
APC:RouteStop()
|
||||
--Cargo:Ungroup()
|
||||
Cargo:Board( APCUnit, 25 )
|
||||
self:__Board( 1, Cargo )
|
||||
Boarding = true
|
||||
|
||||
-- So now this APCUnit has Cargo that is being loaded.
|
||||
-- This will be used further in the logic to follow and to check cargo status.
|
||||
self.APC_Cargo[APCUnit] = Cargo
|
||||
break
|
||||
local CargoBayFreeWeight = APCUnit:GetCargoBayFreeWeight()
|
||||
local CargoWeight = Cargo:GetWeight()
|
||||
|
||||
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
|
||||
|
||||
-- Only when there is space within the bay to load the next cargo item!
|
||||
if CargoBayFreeWeight > CargoWeight then --and CargoBayFreeVolume > CargoVolume then
|
||||
APC:RouteStop()
|
||||
--Cargo:Ungroup()
|
||||
Cargo:Board( APCUnit, 25 )
|
||||
self:__Board( 1, Cargo )
|
||||
|
||||
-- So now this APCUnit has Cargo that is being loaded.
|
||||
-- This will be used further in the logic to follow and to check cargo status.
|
||||
self.APC_Cargo[APCUnit] = Cargo
|
||||
Boarding = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -458,7 +470,31 @@ function AI_CARGO_APC:onafterBoard( APC, From, Event, To, Cargo )
|
||||
if not Cargo:IsLoaded() then
|
||||
self:__Board( 10, Cargo )
|
||||
else
|
||||
self:__Loaded( 1 )
|
||||
for _, APCUnit in pairs( APC:GetUnits() ) do
|
||||
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
|
||||
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
if Cargo:IsUnLoaded() then
|
||||
if Cargo:IsInLoadRadius( APCUnit:GetCoordinate() ) then
|
||||
local CargoBayFreeWeight = APCUnit:GetCargoBayFreeWeight()
|
||||
local CargoWeight = Cargo:GetWeight()
|
||||
|
||||
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
|
||||
|
||||
-- Only when there is space within the bay to load the next cargo item!
|
||||
if CargoBayFreeWeight > CargoWeight then --and CargoBayFreeVolume > CargoVolume then
|
||||
Cargo:Board( APCUnit, 25 )
|
||||
self:__Board( 10, Cargo )
|
||||
-- So now this APCUnit has Cargo that is being loaded.
|
||||
-- This will be used further in the logic to follow and to check cargo status.
|
||||
self.APC_Cargo[APCUnit] = Cargo
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
self:__Loaded( 5, Cargo )
|
||||
end
|
||||
end
|
||||
|
||||
@ -471,7 +507,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @return #boolean Cargo loaded.
|
||||
function AI_CARGO_APC:onbeforeLoaded( APC, From, Event, To )
|
||||
function AI_CARGO_APC:onbeforeLoaded( APC, From, Event, To, Cargo )
|
||||
self:F( { APC, From, Event, To } )
|
||||
|
||||
local Loaded = true
|
||||
@ -484,7 +520,6 @@ function AI_CARGO_APC:onbeforeLoaded( APC, From, Event, To )
|
||||
Loaded = false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if Loaded == true then
|
||||
@ -496,6 +531,9 @@ function AI_CARGO_APC:onbeforeLoaded( APC, From, Event, To )
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--- On after Unload event.
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
@ -511,8 +549,11 @@ function AI_CARGO_APC:onafterUnload( APC, From, Event, To, Deployed )
|
||||
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
|
||||
APC:RouteStop()
|
||||
for _, Cargo in pairs( APCUnit:GetCargo() ) do
|
||||
Cargo:UnBoard()
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
if Cargo:IsLoaded() then
|
||||
Cargo:UnBoard()
|
||||
Cargo:SetDeployed( true )
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -534,6 +575,17 @@ function AI_CARGO_APC:onafterUnboard( APC, From, Event, To, Cargo, Deployed )
|
||||
if not Cargo:IsUnLoaded() then
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
else
|
||||
for _, APCUnit in pairs( APC:GetUnits() ) do
|
||||
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
|
||||
for _, Cargo in pairs( APCUnit:GetCargo() ) do
|
||||
if Cargo:IsLoaded() then
|
||||
Cargo:UnBoard()
|
||||
Cargo:SetDeployed( true )
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
self:__Unloaded( 1, Cargo, Deployed )
|
||||
end
|
||||
end
|
||||
@ -559,22 +611,16 @@ function AI_CARGO_APC:onbeforeUnloaded( APC, From, Event, To, Cargo, Deployed )
|
||||
if APC and APC:IsAlive() then
|
||||
for _, APCUnit in pairs( APC:GetUnits() ) do
|
||||
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
|
||||
local CargoCheck = self.APC_Cargo[APCUnit]
|
||||
if CargoCheck then
|
||||
self:F( { CargoCheck:GetName(), IsUnLoaded = CargoCheck:IsUnLoaded() } )
|
||||
if CargoCheck:IsUnLoaded() == false then
|
||||
AllUnloaded = false
|
||||
break
|
||||
end
|
||||
local IsEmpty = APCUnit:IsCargoEmpty()
|
||||
self:I({ IsEmpty = IsEmpty })
|
||||
if not IsEmpty then
|
||||
AllUnloaded = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if AllUnloaded == true then
|
||||
if Deployed == true then
|
||||
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
Cargo:SetDeployed( true )
|
||||
end
|
||||
self.APC_Cargo = {}
|
||||
end
|
||||
self:Guard()
|
||||
@ -587,6 +633,21 @@ function AI_CARGO_APC:onbeforeUnloaded( APC, From, Event, To, Cargo, Deployed )
|
||||
|
||||
end
|
||||
|
||||
--- On after Unloaded event.
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #string Cargo.Cargo#CARGO Cargo Cargo object.
|
||||
-- @param #boolean Deployed Cargo is deployed.
|
||||
-- @return #boolean All cargo unloaded.
|
||||
function AI_CARGO_APC:onafterUnloaded( APC, From, Event, To, Cargo, Deployed )
|
||||
self:F( { APC, From, Event, To, Cargo:GetName(), Deployed = Deployed } )
|
||||
|
||||
self.Transporting = false
|
||||
|
||||
end
|
||||
|
||||
--- On after Follow event.
|
||||
-- @param #AI_CARGO_APC self
|
||||
@ -632,7 +693,6 @@ function AI_CARGO_APC._Deploy( APC, self )
|
||||
|
||||
if APC:IsAlive() then
|
||||
self:Unload( true )
|
||||
self.Transporting = false
|
||||
self.Relocating = false
|
||||
end
|
||||
end
|
||||
|
||||
@ -23,8 +23,8 @@ AI_CARGO_AIRPLANE = {
|
||||
|
||||
--- Creates a new AI_CARGO_AIRPLANE object.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
-- @param Core.Set#SET_CARGO CargoSet
|
||||
-- @param Wrapper.Group#GROUP Airplane Plane used for transportation of cargo.
|
||||
-- @param Core.Set#SET_CARGO CargoSet Cargo set to be transported.
|
||||
-- @return #AI_CARGO_AIRPLANE
|
||||
function AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
|
||||
|
||||
@ -34,87 +34,124 @@ function AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
|
||||
|
||||
self:SetStartState( "Unloaded" )
|
||||
|
||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
||||
self:AddTransition( { "Unloaded", "Loaded" }, "Pickup", "*" )
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
|
||||
self:AddTransition( "Unloaded", "Load", "Boarding" )
|
||||
self:AddTransition( { "Unloaded", "Boarding" }, "Load", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Board", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Loaded", "Loaded" )
|
||||
self:AddTransition( "Loaded", "Unload", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unloaded", "Unloaded" )
|
||||
self:AddTransition( "Unboarding" , "Unloaded", "Unloaded" )
|
||||
|
||||
self:AddTransition( "*", "Landed", "*" )
|
||||
self:AddTransition( "*", "Home" , "*" )
|
||||
|
||||
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
||||
|
||||
--- Pickup Handler OnBefore for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnBeforePickup
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troops are picked up.
|
||||
-- @param #number Speed in km/h for travelling to pickup base.
|
||||
-- @return #boolean
|
||||
|
||||
--- Pickup Handler OnAfter for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterPickup
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troops are picked up.
|
||||
-- @param #number Speed in km/h for travelling to pickup base.
|
||||
|
||||
--- Pickup Trigger for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] Pickup
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troops are picked up.
|
||||
-- @param #number Speed in km/h for travelling to pickup base.
|
||||
|
||||
--- Pickup Asynchronous Trigger for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] __Pickup
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param #number Delay
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Delay Delay in seconds.
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troops are picked up.
|
||||
-- @param #number Speed in km/h for travelling to pickup base.
|
||||
|
||||
--- Deploy Handler OnBefore for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnBeforeDeploy
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase where troops are deployed.
|
||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
||||
-- @return #boolean
|
||||
|
||||
--- Deploy Handler OnAfter for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterDeploy
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase where troops are deployed.
|
||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
||||
|
||||
--- Deploy Trigger for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] Deploy
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase where troops are deployed.
|
||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
||||
|
||||
--- Deploy Asynchronous Trigger for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] __Deploy
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Delay
|
||||
-- @param #number Delay Delay in seconds.
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase where troops are deployed.
|
||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
||||
|
||||
--- On after Loaded event, i.e. triggered when the cargo is inside the carrier.
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterLoaded
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
|
||||
-- Set carrier.
|
||||
self:SetCarrier( Airplane )
|
||||
|
||||
Airplane:SetCargoBayWeightLimit()
|
||||
|
||||
self.Relocating = true
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set the Carrier.
|
||||
function AI_CARGO_AIRPLANE:IsTransporting()
|
||||
|
||||
return self.Transporting == true
|
||||
end
|
||||
|
||||
function AI_CARGO_AIRPLANE:IsRelocating()
|
||||
|
||||
return self.Relocating == true
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Set the Carrier (controllable). Also initializes events for carrier and defines the coalition.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
-- @return #AI_CARGO_AIRPLANE
|
||||
-- @param Wrapper.Group#GROUP Airplane Transport plane.
|
||||
-- @return #AI_CARGO_AIRPLANE self
|
||||
function AI_CARGO_AIRPLANE:SetCarrier( Airplane )
|
||||
|
||||
local AICargo = self
|
||||
@ -155,7 +192,8 @@ function AI_CARGO_AIRPLANE:SetCarrier( Airplane )
|
||||
|
||||
|
||||
function Airplane:OnEventEngineShutdown( EventData )
|
||||
AICargo:Landed()
|
||||
AICargo.Relocating = false
|
||||
AICargo:Landed( self.Airplane )
|
||||
end
|
||||
|
||||
self.Coalition = self.Airplane:GetCoalition()
|
||||
@ -168,7 +206,7 @@ end
|
||||
|
||||
--- Find a free Carrier within a range.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Radius
|
||||
-- @return Wrapper.Group#GROUP NewCarrier
|
||||
function AI_CARGO_AIRPLANE:FindCarrier( Coordinate, Radius )
|
||||
@ -190,25 +228,32 @@ function AI_CARGO_AIRPLANE:FindCarrier( Coordinate, Radius )
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
--- On after "Landed" event. Called on engine shutdown and initiates the pickup mission or unloading event.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_AIRPLANE:onafterLanded( Airplane, From, Event, To )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self:F({Airplane, From, Event, To})
|
||||
|
||||
if Airplane and Airplane:IsAlive()~=nil then
|
||||
|
||||
-- Aircraft was sent to this airbase to pickup troops. Initiate loadling.
|
||||
if self.RoutePickup == true then
|
||||
self:Load( Airplane:GetPointVec2() )
|
||||
env.info("FF load airplane "..Airplane:GetName())
|
||||
self:Load( Airplane:GetCoordinate() )
|
||||
self.RoutePickup = false
|
||||
self.Relocating = true
|
||||
end
|
||||
|
||||
-- Aircraft was send to this airbase to deploy troops. Initiate unloading.
|
||||
if self.RouteDeploy == true then
|
||||
self:Unload()
|
||||
self.RouteDeploy = false
|
||||
self.Transporting = false
|
||||
self.Relocating = false
|
||||
end
|
||||
|
||||
end
|
||||
@ -216,231 +261,344 @@ function AI_CARGO_AIRPLANE:onafterLanded( Airplane, From, Event, To )
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Speed
|
||||
--- On after "Pickup" event. Routes transport to pickup airbase.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where the troops as picked up.
|
||||
-- @param #number Speed in km/h for travelling to pickup base.
|
||||
function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Airbase, Speed )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self:Route( Airplane, Airbase, Speed )
|
||||
self.RoutePickup = true
|
||||
self.Airbase = Airbase
|
||||
if Airplane and Airplane:IsAlive()~=nil then
|
||||
env.info("FF onafterpick aircraft alive")
|
||||
|
||||
-- Get closest airbase of current position.
|
||||
local ClosestAirbase, DistToAirbase=Airplane:GetCoordinate():GetClosestAirbase()
|
||||
|
||||
env.info("FF onafterpickup closest airbase "..ClosestAirbase:GetName())
|
||||
|
||||
-- Two cases. Aircraft spawned in air or at an airbase.
|
||||
if Airplane:InAir() then
|
||||
self.Airbase=nil --> route will start in air
|
||||
else
|
||||
self.Airbase=ClosestAirbase
|
||||
end
|
||||
|
||||
-- Distance from closest to pickup airbase ==> we need to know if we are already at the pickup airbase.
|
||||
local Dist=Airbase:GetCoordinate():Get2DDistance(ClosestAirbase:GetCoordinate())
|
||||
env.info("Distance closest to pickup airbase = "..Dist)
|
||||
|
||||
if Airplane:InAir() or Dist>500 then
|
||||
|
||||
env.info("FF onafterpickup routing to airbase "..ClosestAirbase:GetName())
|
||||
|
||||
-- Route aircraft to pickup airbase.
|
||||
self:Route( Airplane, Airbase, Speed )
|
||||
|
||||
-- Set airbase as starting point in the next Route() call.
|
||||
self.Airbase = Airbase
|
||||
|
||||
-- Aircraft is on a pickup mission.
|
||||
self.RoutePickup = true
|
||||
|
||||
-- Unclear!?
|
||||
self.Transporting = true
|
||||
self.Relocating = false
|
||||
else
|
||||
env.info("FF onafterpick calling landed")
|
||||
|
||||
-- We are already at the right airbase ==> Landed ==> triggers loading of troops. Is usually called at engine shutdown event.
|
||||
self.RoutePickup=true
|
||||
self:Landed()
|
||||
|
||||
end
|
||||
else
|
||||
env.info("FF onafterpick aircraft not alive")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Speed
|
||||
--- On after Depoly event. Routes plane to the airbase where the troops are deployed.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troups should be deployed.
|
||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
||||
function AI_CARGO_AIRPLANE:onafterDeploy( Airplane, From, Event, To, Airbase, Speed )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
if Airplane and Airplane:IsAlive()~=nil then
|
||||
|
||||
-- Activate uncontrolled airplane.
|
||||
if Airplane:IsAlive()==false then
|
||||
Airplane:SetCommand({id = 'Start', params = {}})
|
||||
end
|
||||
|
||||
-- Route to destination airbase.
|
||||
self:Route( Airplane, Airbase, Speed )
|
||||
|
||||
-- Aircraft is on a depoly mission.
|
||||
self.RouteDeploy = true
|
||||
|
||||
-- Set destination airbase for next :Route() command.
|
||||
self.Airbase = Airbase
|
||||
|
||||
self.Transporting = true
|
||||
self.Relocating = false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
--- On after Load event. Checks if cargo is inside the load radius and if so starts the boarding process.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Point#COORDINATE Coordinate Place where the cargo is guided to if it is inside the load radius.
|
||||
function AI_CARGO_AIRPLANE:onafterLoad( Airplane, From, Event, To, Coordinate )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
if Airplane and Airplane:IsAlive() ~= nil then
|
||||
|
||||
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||
if Cargo:IsInLoadRadius( Coordinate ) then
|
||||
self:__Board( 5 )
|
||||
Cargo:Board( Airplane, 25 )
|
||||
self.Cargo = Cargo
|
||||
break
|
||||
for _,_Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||
self:F({_Cargo:GetName()})
|
||||
local Cargo=_Cargo --Cargo.Cargo#CARGO
|
||||
local InRadius = Cargo:IsInLoadRadius( Coordinate )
|
||||
if InRadius then
|
||||
|
||||
-- Is there a cargo still unloaded?
|
||||
if Cargo:IsUnLoaded() == true then
|
||||
|
||||
self:__Board( 5, Cargo )
|
||||
Cargo:Board( Airplane, 25 )
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
function AI_CARGO_AIRPLANE:onafterBoard( Airplane, From, Event, To )
|
||||
--- On after Board event. Cargo is inside the load radius and boarding is performed.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function AI_CARGO_AIRPLANE:onafterBoard( Airplane, From, Event, To, Cargo )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self:F({ IsLoaded = self.Cargo:IsLoaded() } )
|
||||
if not self.Cargo:IsLoaded() then
|
||||
self:__Board( 10 )
|
||||
|
||||
self:F({ IsLoaded = Cargo:IsLoaded() } )
|
||||
|
||||
if not Cargo:IsLoaded() then
|
||||
self:__Board( 10, Cargo )
|
||||
else
|
||||
self:__Loaded( 1 )
|
||||
-- Check if another cargo can be loaded into the airplane.
|
||||
for _,_Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||
|
||||
self:F({_Cargo:GetName()})
|
||||
local Cargo =_Cargo --Cargo.Cargo#CARGO
|
||||
|
||||
-- Is there a cargo still unloaded?
|
||||
if Cargo:IsUnLoaded() == true then
|
||||
|
||||
-- Only when the cargo is within load radius.
|
||||
local InRadius = Cargo:IsInLoadRadius( Airplane:GetCoordinate() )
|
||||
if InRadius then
|
||||
|
||||
local CargoBayFreeWeight = Airplane:GetCargoBayFreeWeight()
|
||||
--local CargoBayFreeVolume = Airplane:GetCargoBayFreeVolume()
|
||||
|
||||
local CargoWeight = Cargo:GetWeight()
|
||||
--local CargoVolume = Cargo:GetVolume()
|
||||
|
||||
-- Only when there is space within the bay to load the next cargo item!
|
||||
if CargoBayFreeWeight > CargoWeight then --and CargoBayFreeVolume > CargoVolume then
|
||||
|
||||
-- ok, board.
|
||||
self:__Load( 5, Airplane:GetCoordinate() )
|
||||
|
||||
-- And start the boarding loop for the AI_CARGO_AIRPLANE object until the cargo is boarded.
|
||||
--Cargo:Board( Airplane, 25 )
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
self:__Loaded( 1, Cargo )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
function AI_CARGO_AIRPLANE:onafterLoaded( Airplane, From, Event, To )
|
||||
--- On after Loaded event. Cargo is inside the carrier and ready to be transported.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function AI_CARGO_AIRPLANE:onafterLoaded( Airplane, From, Event, To, Cargo )
|
||||
|
||||
env.info("FF troops loaded into cargo plane")
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self:F( { "Transporting" } )
|
||||
self.Transporting = true -- This will only be executed when there is no cargo boarded anymore. The dispatcher will then kick-off the deploy cycle!
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
--- On after Unload event. Cargo is beeing unloaded, i.e. the unboarding process is started.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function AI_CARGO_AIRPLANE:onafterUnload( Airplane, From, Event, To )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self.Cargo:UnBoard()
|
||||
self:__Unboard( 10 )
|
||||
end
|
||||
local Cargos = Airplane:GetCargo()
|
||||
for CargoID, Cargo in pairs( Cargos ) do
|
||||
|
||||
end
|
||||
local Angle = 180
|
||||
local CargoCarrierHeading = Airplane:GetHeading() -- Get Heading of object in degrees.
|
||||
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
|
||||
self:T( { CargoCarrierHeading, CargoDeployHeading } )
|
||||
local CargoDeployCoordinate = Airplane:GetPointVec2():Translate( 150, CargoDeployHeading )
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
function AI_CARGO_AIRPLANE:onafterUnboard( Airplane, From, Event, To )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
if not self.Cargo:IsUnLoaded() then
|
||||
self:__Unboard( 10 )
|
||||
else
|
||||
self:__Unloaded( 1 )
|
||||
Cargo:UnBoard( CargoDeployCoordinate )
|
||||
Cargo:SetDeployed( true )
|
||||
self:__Unboard( 10, Cargo )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
function AI_CARGO_AIRPLANE:onafterUnloaded( Airplane, From, Event, To )
|
||||
--- On after Unboard event. Checks if unboarding process is finished.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function AI_CARGO_AIRPLANE:onafterUnboard( Airplane, From, Event, To, Cargo )
|
||||
|
||||
self:E( { "Unboard", Cargo } )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
if not Cargo:IsUnLoaded() then
|
||||
self:__Unboard( 10, Cargo )
|
||||
else
|
||||
local Cargos = Airplane:GetCargo()
|
||||
for CargoID, Cargo in pairs( Cargos ) do
|
||||
if Cargo:IsLoaded() then
|
||||
local Angle = 180
|
||||
local CargoCarrierHeading = Airplane:GetHeading() -- Get Heading of object in degrees.
|
||||
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
|
||||
self:T( { CargoCarrierHeading, CargoDeployHeading } )
|
||||
local CargoDeployCoordinate = Airplane:GetPointVec2():Translate( 150, CargoDeployHeading )
|
||||
Cargo:UnBoard( CargoDeployCoordinate )
|
||||
Cargo:SetDeployed( true )
|
||||
|
||||
self:__Unboard( 10, Cargo )
|
||||
return
|
||||
end
|
||||
end
|
||||
self:__Unloaded( 1, Cargo )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- On after Unloaded event. Cargo has been unloaded, i.e. the unboarding process is finished.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Cargo.Cargo#CARGO Cargo
|
||||
function AI_CARGO_AIRPLANE:onafterUnloaded( Airplane, From, Event, To, Cargo )
|
||||
|
||||
self:E( { "Unloaded", Cargo } )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self.Airplane = Airplane
|
||||
self.Transporting = false -- This will only be executed when there is no cargo onboard anymore. The dispatcher will then kick-off the pickup cycle!
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Route the airplane from one airport or it's current position to another airbase.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Airplane group to be routed.
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase.
|
||||
-- @param #number Speed Speed in km/h. Default is 80% of max possible speed the group can do.
|
||||
-- @param #boolean Uncontrolled If true, spawn group in uncontrolled state.
|
||||
function AI_CARGO_AIRPLANE:Route( Airplane, Airbase, Speed, Uncontrolled )
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_AIRPLANE:Route( Airplane, Airbase, Speed )
|
||||
if Airplane and Airplane:IsAlive()~=nil then
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
|
||||
local PointVec3 = Airplane:GetPointVec3()
|
||||
|
||||
local Takeoff = SPAWN.Takeoff.Hot
|
||||
-- Set takeoff type.
|
||||
local Takeoff = SPAWN.Takeoff.Cold
|
||||
|
||||
-- Get template of group.
|
||||
local Template = Airplane:GetTemplate()
|
||||
|
||||
if Template then
|
||||
-- Nil check
|
||||
if Template==nil then
|
||||
return
|
||||
end
|
||||
|
||||
local Points = {}
|
||||
-- Waypoints of the route.
|
||||
local Points={}
|
||||
|
||||
if self.Airbase then
|
||||
|
||||
local FromWaypoint = Template.route.points[1]
|
||||
|
||||
-- These are only for ships.
|
||||
FromWaypoint.linkUnit = nil
|
||||
FromWaypoint.helipadId = nil
|
||||
FromWaypoint.airdromeId = nil
|
||||
|
||||
local AirbaseID = self.Airbase:GetID()
|
||||
local AirbaseCategory = self.Airbase:GetDesc().category
|
||||
|
||||
FromWaypoint.airdromeId = AirbaseID
|
||||
|
||||
FromWaypoint.alt = 0
|
||||
|
||||
FromWaypoint.type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type
|
||||
FromWaypoint.action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action
|
||||
-- To point.
|
||||
local AirbasePointVec2 = Airbase:GetPointVec2()
|
||||
local ToWaypoint = AirbasePointVec2:WaypointAir(
|
||||
POINT_VEC3.RoutePointAltType.BARO,
|
||||
"Land",
|
||||
"Landing",
|
||||
Speed or Airplane:GetSpeedMax()*0.8
|
||||
)
|
||||
ToWaypoint["airdromeId"] = Airbase:GetID()
|
||||
ToWaypoint["speed_locked"] = true
|
||||
|
||||
|
||||
-- Translate the position of the Group Template to the Vec3.
|
||||
for UnitID = 1, #Template.units do
|
||||
self:T( 'Before Translation SpawnTemplate.units['..UnitID..'].x = ' .. Template.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. Template.units[UnitID].y )
|
||||
-- If self.Airbase~=nil then group is currently at an airbase, where it should be respawned.
|
||||
if self.Airbase then
|
||||
|
||||
-- These cause a lot of confusion.
|
||||
local UnitTemplate = Template.units[UnitID]
|
||||
-- Second point of the route. First point is done in RespawnAtCurrentAirbase() routine.
|
||||
Template.route.points[2] = ToWaypoint
|
||||
|
||||
UnitTemplate.parking = 15
|
||||
UnitTemplate.parking_id = "1"
|
||||
UnitTemplate.alt = 0
|
||||
-- Respawn group at the current airbase.
|
||||
Airplane:RespawnAtCurrentAirbase(Template, Takeoff, Uncontrolled)
|
||||
|
||||
local SX = UnitTemplate.x
|
||||
local SY = UnitTemplate.y
|
||||
local BX = FromWaypoint.x
|
||||
local BY = FromWaypoint.y
|
||||
local TX = PointVec3.x + ( SX - BX )
|
||||
local TY = PointVec3.z + ( SY - BY )
|
||||
else
|
||||
|
||||
UnitTemplate.x = TX
|
||||
UnitTemplate.y = TY
|
||||
-- From point.
|
||||
local GroupPoint = Airplane:GetVec2()
|
||||
local FromWaypoint = {}
|
||||
FromWaypoint.x = GroupPoint.x
|
||||
FromWaypoint.y = GroupPoint.y
|
||||
FromWaypoint.type = "Turning Point"
|
||||
FromWaypoint.action = "Turning Point"
|
||||
FromWaypoint.speed = Airplane:GetSpeedMax()*0.8
|
||||
|
||||
self:T( 'After Translation SpawnTemplate.units['..UnitID..'].x = ' .. UnitTemplate.x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. UnitTemplate.y )
|
||||
end
|
||||
|
||||
FromWaypoint.x = PointVec3.x
|
||||
FromWaypoint.y = PointVec3.z
|
||||
|
||||
Points[#Points+1] = FromWaypoint
|
||||
else
|
||||
|
||||
local GroupPoint = Airplane:GetVec2()
|
||||
local GroupVelocity = Airplane:GetUnit(1):GetDesc().speedMax
|
||||
|
||||
local FromWaypoint = {}
|
||||
FromWaypoint.x = GroupPoint.x
|
||||
FromWaypoint.y = GroupPoint.y
|
||||
FromWaypoint.type = "Turning Point"
|
||||
FromWaypoint.action = "Turning Point"
|
||||
FromWaypoint.speed = GroupVelocity
|
||||
|
||||
Points[#Points+1] = FromWaypoint
|
||||
end
|
||||
|
||||
local AirbasePointVec2 = Airbase:GetPointVec2()
|
||||
local ToWaypoint = AirbasePointVec2:WaypointAir(
|
||||
POINT_VEC3.RoutePointAltType.BARO,
|
||||
"Land",
|
||||
"Landing",
|
||||
Speed or Airplane:GetUnit(1):GetDesc().speedMax
|
||||
)
|
||||
|
||||
ToWaypoint["airdromeId"] = Airbase:GetID()
|
||||
ToWaypoint["speed_locked"] = true,
|
||||
|
||||
self:F( ToWaypoint )
|
||||
|
||||
Points[#Points+1] = ToWaypoint
|
||||
-- The two route points.
|
||||
Points[1] = FromWaypoint
|
||||
Points[2] = ToWaypoint
|
||||
|
||||
local PointVec3 = Airplane:GetPointVec3()
|
||||
Template.x = PointVec3.x
|
||||
Template.y = PointVec3.z
|
||||
|
||||
self:T3( Points )
|
||||
Template.route.points = Points
|
||||
|
||||
--self:Respawn( Template )
|
||||
local GroupSpawned = Airplane:Respawn(Template)
|
||||
|
||||
local GroupSpawned = Airplane:Respawn( Template )
|
||||
|
||||
return GroupSpawned
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -74,7 +74,7 @@
|
||||
AI_CARGO_DISPATCHER = {
|
||||
ClassName = "AI_CARGO_DISPATCHER",
|
||||
SetCarrier = nil,
|
||||
SetDeployZones = nil,
|
||||
DeployZonesSet = nil,
|
||||
AI_Cargo = {},
|
||||
PickupCargo = {}
|
||||
}
|
||||
@ -90,23 +90,21 @@ AI_CARGO_DISPATCHER.PickupCargo = {}
|
||||
-- @param #AI_CARGO_DISPATCHER self
|
||||
-- @param Core.Set#SET_GROUP SetCarrier
|
||||
-- @param Core.Set#SET_CARGO SetCargo
|
||||
-- @param Core.Set#SET_ZONE SetDeployZones
|
||||
-- @return #AI_CARGO_DISPATCHER
|
||||
-- @usage
|
||||
--
|
||||
-- -- Create a new cargo dispatcher
|
||||
-- SetCarrier = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart()
|
||||
-- SetCargo = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- SetCarriers = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart()
|
||||
-- SetCargos = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- SetDeployZone = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
||||
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZone )
|
||||
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo )
|
||||
--
|
||||
function AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZones )
|
||||
function AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo )
|
||||
|
||||
local self = BASE:Inherit( self, FSM:New() ) -- #AI_CARGO_DISPATCHER
|
||||
|
||||
self.SetCarrier = SetCarrier -- Core.Set#SET_GROUP
|
||||
self.SetCargo = SetCargo -- Core.Set#SET_CARGO
|
||||
self.SetDeployZones = SetDeployZones -- Core.Set#SET_ZONE
|
||||
|
||||
self:SetStartState( "Idle" )
|
||||
|
||||
@ -144,6 +142,58 @@ function AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZones )
|
||||
end
|
||||
|
||||
|
||||
--- Creates a new AI_CARGO_DISPATCHER object.
|
||||
-- @param #AI_CARGO_DISPATCHER self
|
||||
-- @param Core.Set#SET_GROUP SetCarrier
|
||||
-- @param Core.Set#SET_CARGO SetCargo
|
||||
-- @param Core.Set#SET_ZONE DeployZonesSet
|
||||
-- @return #AI_CARGO_DISPATCHER
|
||||
-- @usage
|
||||
--
|
||||
-- -- Create a new cargo dispatcher
|
||||
-- SetCarriers = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart()
|
||||
-- SetCargos = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- DeployZonesSet = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
||||
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZone )
|
||||
--
|
||||
function AI_CARGO_DISPATCHER:NewWithZones( SetCarriers, SetCargos, DeployZonesSet )
|
||||
|
||||
local self = AI_CARGO_DISPATCHER:New( SetCarriers, SetCargos ) -- #AI_CARGO_DISPATCHER
|
||||
|
||||
self.DeployZonesSet = DeployZonesSet
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Creates a new AI_CARGO_DISPATCHER object.
|
||||
-- @param #AI_CARGO_DISPATCHER self
|
||||
-- @param Core.Set#SET_GROUP SetCarrier
|
||||
-- @param Core.Set#SET_CARGO SetCargo
|
||||
-- @param Core.Set#SET_AIRBASE PickupAirbasesSet
|
||||
-- @param Core.Set#SET_AIRBASE DeployAirbasesSet
|
||||
-- @return #AI_CARGO_DISPATCHER
|
||||
-- @usage
|
||||
--
|
||||
-- -- Create a new cargo dispatcher
|
||||
-- SetCarriers = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart()
|
||||
-- SetCargos = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- PickupAirbasesSet = SET_AIRBASES:New()
|
||||
-- DeployAirbasesSet = SET_AIRBASES:New()
|
||||
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, PickupAirbasesSet, DeployAirbasesSet )
|
||||
--
|
||||
function AI_CARGO_DISPATCHER:NewWithAirbases( SetCarriers, SetCargos, PickupAirbasesSet, DeployAirbasesSet )
|
||||
|
||||
local self = AI_CARGO_DISPATCHER:New( SetCarriers, SetCargos ) -- #AI_CARGO_DISPATCHER
|
||||
|
||||
self.DeployAirbasesSet = DeployAirbasesSet
|
||||
self.PickupAirbasesSet = PickupAirbasesSet
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Set the home zone.
|
||||
-- When there is nothing anymore to pickup, the carriers will go to a random coordinate in this zone.
|
||||
-- They will await here new orders.
|
||||
@ -166,6 +216,31 @@ function AI_CARGO_DISPATCHER:SetHomeZone( HomeZone )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the home airbase. This is for air units, i.e. helicopters and airplanes.
|
||||
-- When there is nothing anymore to pickup, the carriers will go back to their home base. They will await here new orders.
|
||||
-- @param #AI_CARGO_DISPATCHER self
|
||||
-- @param Wrapper.Airbase#AIRBASE HomeBase Airbase where the carriers will go after all pickup assignments are done.
|
||||
-- @return #AI_CARGO_DISPATCHER self
|
||||
function AI_CARGO_DISPATCHER:SetHomeBase( HomeBase )
|
||||
|
||||
self.HomeBase = HomeBase
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set the home base.
|
||||
-- When there is nothing anymore to pickup, the carriers will return to their home airbase. There they will await new orders.
|
||||
-- @param #AI_CARGO_DISPATCHER self
|
||||
-- @param Wrapper.Airbase#AIRBASE HomeBase The airbase where the carrier will go to, once they completed all pending assignments.
|
||||
-- @return #AI_CARGO_DISPATCHER self
|
||||
function AI_CARGO_DISPATCHER:SetHomeBase( HomeBase )
|
||||
|
||||
self.HomeBase = HomeBase
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Sets or randomizes the pickup location for the carrier around the cargo coordinate in a radius defined an outer and optional inner radius.
|
||||
-- This radius is influencing the location where the carrier will land to pickup the cargo.
|
||||
@ -328,8 +403,9 @@ function AI_CARGO_DISPATCHER:onafterMonitor()
|
||||
|
||||
-- The Pickup sequence ...
|
||||
-- Check if this Carrier need to go and Pickup something...
|
||||
self:I( { IsTransporting = AI_Cargo:IsTransporting() } )
|
||||
if AI_Cargo:IsTransporting() == false then
|
||||
-- So, if the cargo bay is not full yet with cargo to be loaded ...
|
||||
self:I( { IsRelocating = AI_Cargo:IsRelocating(), IsTransporting = AI_Cargo:IsTransporting() } )
|
||||
if AI_Cargo:IsRelocating() == false and AI_Cargo:IsTransporting() == false then
|
||||
-- ok, so there is a free Carrier
|
||||
-- now find the first cargo that is Unloaded
|
||||
|
||||
@ -338,7 +414,7 @@ function AI_CARGO_DISPATCHER:onafterMonitor()
|
||||
for CargoName, Cargo in pairs( self.SetCargo:GetSet() ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
self:F( { Cargo = Cargo:GetName(), UnLoaded = Cargo:IsUnLoaded(), Deployed = Cargo:IsDeployed(), PickupCargo = self.PickupCargo[Carrier] ~= nil } )
|
||||
if Cargo:IsUnLoaded() and not Cargo:IsDeployed() then
|
||||
if Cargo:IsUnLoaded() == true and Cargo:IsDeployed() == false then
|
||||
local CargoCoordinate = Cargo:GetCoordinate()
|
||||
local CoordinateFree = true
|
||||
for CarrierPickup, Coordinate in pairs( self.PickupCargo ) do
|
||||
@ -358,10 +434,20 @@ function AI_CARGO_DISPATCHER:onafterMonitor()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if PickupCargo then
|
||||
self.CarrierHome[Carrier] = nil
|
||||
local PickupCoordinate = PickupCargo:GetCoordinate():GetRandomCoordinateInRadius( self.PickupOuterRadius, self.PickupInnerRadius )
|
||||
AI_Cargo:Pickup( PickupCoordinate, math.random( self.PickupMinSpeed, self.PickupMaxSpeed ) )
|
||||
|
||||
if self.PickupAirbasesSet then
|
||||
-- Find airbase within 2km from the cargo with the set.
|
||||
local PickupAirbase = self.PickupAirbasesSet:FindAirbaseInRange( PickupCoordinate, 4000 )
|
||||
if PickupAirbase then
|
||||
AI_Cargo:Pickup( PickupAirbase, math.random( self.PickupMinSpeed, self.PickupMaxSpeed ) )
|
||||
end
|
||||
else
|
||||
AI_Cargo:Pickup( PickupCoordinate, math.random( self.PickupMinSpeed, self.PickupMaxSpeed ) )
|
||||
end
|
||||
break
|
||||
else
|
||||
if self.HomeZone then
|
||||
@ -464,14 +550,23 @@ end
|
||||
-- @return #AI_CARGO_DISPATCHER
|
||||
function AI_CARGO_DISPATCHER:OnAfterLoaded( From, Event, To, Carrier, Cargo )
|
||||
|
||||
local DeployZone = self.SetDeployZones:GetRandomZone()
|
||||
if self.DeployZonesSet then
|
||||
|
||||
local DeployCoordinate = DeployZone:GetCoordinate():GetRandomCoordinateInRadius( self.DeployOuterRadius, self.DeployInnerRadius )
|
||||
self.AI_Cargo[Carrier]:Deploy( DeployCoordinate, math.random( self.DeployMinSpeed, self.DeployMaxSpeed ) )
|
||||
local DeployZone = self.DeployZonesSet:GetRandomZone()
|
||||
|
||||
self.PickupCargo[Carrier] = nil
|
||||
local DeployCoordinate = DeployZone:GetCoordinate():GetRandomCoordinateInRadius( self.DeployOuterRadius, self.DeployInnerRadius )
|
||||
self.AI_Cargo[Carrier]:Deploy( DeployCoordinate, math.random( self.DeployMinSpeed, self.DeployMaxSpeed ) )
|
||||
|
||||
end
|
||||
|
||||
if self.DeployAirbasesSet then
|
||||
|
||||
if self.AI_Cargo[Carrier]:IsTransporting() == true then
|
||||
local DeployAirbase = self.DeployAirbasesSet:GetRandomAirbase()
|
||||
self.AI_Cargo[Carrier]:Deploy( DeployAirbase, math.random( self.DeployMinSpeed, self.DeployMaxSpeed ) )
|
||||
end
|
||||
end
|
||||
|
||||
self.PickupCargo[Carrier] = nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -103,7 +103,7 @@ AI_CARGO_DISPATCHER_APC = {
|
||||
--
|
||||
function AI_CARGO_DISPATCHER_APC:New( SetAPC, SetCargo, SetDeployZone, CombatRadius )
|
||||
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( SetAPC, SetCargo, SetDeployZone ) ) -- #AI_CARGO_DISPATCHER_APC
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:NewWithZones( SetAPC, SetCargo, SetDeployZone ) ) -- #AI_CARGO_DISPATCHER_APC
|
||||
|
||||
self.CombatRadius = CombatRadius or 500
|
||||
|
||||
|
||||
@ -16,8 +16,8 @@
|
||||
--- Brings a dynamic cargo handling capability for AI groups.
|
||||
--
|
||||
-- Airplanes can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
-- The AI\_CARGO\_DISPATCHER\_AIRPLANE module uses the @{Cargo} capabilities within the MOOSE framework.
|
||||
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\_DISPATCHER\_AIRPLANE object recognize the cargo.
|
||||
-- The AI_CARGO_DISPATCHER_AIRPLANE module uses the @{Cargo} capabilities within the MOOSE framework.
|
||||
-- CARGO derived objects must be declared within the mission to make the AI_CARGO_DISPATCHER_AIRPLANE object recognize the cargo.
|
||||
-- Please consult the @{Cargo} module for more information.
|
||||
--
|
||||
--
|
||||
@ -29,23 +29,33 @@ AI_CARGO_DISPATCHER_AIRPLANE = {
|
||||
|
||||
--- Creates a new AI_CARGO_DISPATCHER_AIRPLANE object.
|
||||
-- @param #AI_CARGO_DISPATCHER_AIRPLANE self
|
||||
-- @param Core.Set#SET_GROUP SetAirplane
|
||||
-- @param Core.Set#SET_CARGO SetCargo
|
||||
-- @param Core.Set#SET_ZONE SetDeployZone
|
||||
-- @return #AI_CARGO_DISPATCHER_AIRPLANE
|
||||
-- @param Core.Set#SET_GROUP SetAirplanes Set of cargo transport airplanes.
|
||||
-- @param Core.Set#SET_CARGO SetCargos Set of cargo, which is supposed to be transported.
|
||||
-- @param Core.Set#SET_AIRBASE PickupAirbasesSet Set of airbases where the cargo has to be picked up.
|
||||
-- @param Core.Set#SET_AIRBASE DeployAirbasesSet Set of airbases where the cargo is deployed. Choice for each cargo is random.
|
||||
-- @return #AI_CARGO_DISPATCHER_AIRPLANE self
|
||||
-- @usage
|
||||
--
|
||||
-- -- Create a new cargo dispatcher
|
||||
-- SetAirplane = SET_GROUP:New():FilterPrefixes( "Airplane" ):FilterStart()
|
||||
-- SetCargo = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- SetDeployZone = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
||||
-- AICargoDispatcher = AI_CARGO_DISPATCHER_AIRPLANE:New( SetAirplane, SetCargo )
|
||||
-- SetAirplanes = SET_GROUP:New():FilterPrefixes( "Airplane" ):FilterStart()
|
||||
-- SetCargos = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- PickupAirbasesSet = SET_AIRBASE:New()
|
||||
-- DeployAirbasesSet = SET_AIRBASE:New()
|
||||
-- AICargoDispatcher = AI_CARGO_DISPATCHER_AIRPLANE:New( SetAirplanes, SetCargos, PickupAirbasesSet, DeployAirbasesSet )
|
||||
--
|
||||
function AI_CARGO_DISPATCHER_AIRPLANE:New( SetAirplane, SetCargo, SetDeployZones )
|
||||
function AI_CARGO_DISPATCHER_AIRPLANE:New( SetAirplanes, SetCargos, PickupAirbasesSet, DeployAirbasesSet )
|
||||
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( SetAirplane, SetCargo, SetDeployZones ) ) -- #AI_CARGO_DISPATCHER_AIRPLANE
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:NewWithAirbases( SetAirplanes, SetCargos, PickupAirbasesSet, DeployAirbasesSet ) ) -- #AI_CARGO_DISPATCHER_AIRPLANE
|
||||
|
||||
self:SetDeploySpeed( 200, 150 )
|
||||
self:SetPickupSpeed( 200, 150 )
|
||||
self:SetPickupRadius( 0, 0 )
|
||||
self:SetDeployRadius( 0, 0 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function AI_CARGO_DISPATCHER_AIRPLANE:AICargo( Airplane, SetCargo )
|
||||
|
||||
return AI_CARGO_AIRPLANE:New( Airplane, SetCargo )
|
||||
end
|
||||
|
||||
@ -102,7 +102,7 @@ AI_CARGO_DISPATCHER_HELICOPTER = {
|
||||
--
|
||||
function AI_CARGO_DISPATCHER_HELICOPTER:New( SetHelicopter, SetCargo, SetDeployZones )
|
||||
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( SetHelicopter, SetCargo, SetDeployZones ) ) -- #AI_CARGO_DISPATCHER_HELICOPTER
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:NewWithZones( SetHelicopter, SetCargo, SetDeployZones ) ) -- #AI_CARGO_DISPATCHER_HELICOPTER
|
||||
|
||||
self:SetDeploySpeed( 200, 150 )
|
||||
self:SetPickupSpeed( 200, 150 )
|
||||
|
||||
@ -20,7 +20,8 @@
|
||||
-- @field #AI_CARGO_HELICOPTER
|
||||
AI_CARGO_HELICOPTER = {
|
||||
ClassName = "AI_CARGO_HELICOPTER",
|
||||
Coordinate = nil -- Core.Point#COORDINATE,
|
||||
Coordinate = nil, -- Core.Point#COORDINATE,
|
||||
Helicopter_Cargo = {},
|
||||
}
|
||||
|
||||
AI_CARGO_QUEUE = {}
|
||||
@ -43,7 +44,7 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
|
||||
self:AddTransition( "Unloaded", "Load", "Boarding" )
|
||||
self:AddTransition( { "Unloaded", "Loading" }, "Load", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Board", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Loaded", "Loaded" )
|
||||
self:AddTransition( "Loaded", "Unload", "Unboarding" )
|
||||
@ -73,17 +74,20 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Pickup Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] Pickup
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Pickup Asynchronous Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] __Pickup
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param #number Delay
|
||||
-- @param #number Delay Delay in seconds.
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h to go to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Deploy Handler OnBefore for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] OnBeforeDeploy
|
||||
@ -91,7 +95,8 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @return #boolean
|
||||
|
||||
--- Deploy Handler OnAfter for AI_CARGO_HELICOPTER
|
||||
@ -101,17 +106,20 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Deploy Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] Deploy
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which the cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Deploy Asynchronous Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] __Deploy
|
||||
-- @param #number Delay Delay in seconds.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Delay
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which the cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
|
||||
-- We need to capture the Crash events for the helicopters.
|
||||
@ -137,6 +145,13 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
end
|
||||
)
|
||||
|
||||
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
|
||||
HelicopterUnit:SetCargoBayWeightLimit()
|
||||
end
|
||||
|
||||
self.Relocating = false
|
||||
self.Transporting = false
|
||||
|
||||
self:SetCarrier( Helicopter )
|
||||
|
||||
return self
|
||||
@ -217,7 +232,8 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
||||
|
||||
if self.RoutePickup == true then
|
||||
if Helicopter:GetHeight( true ) <= 5 and Helicopter:GetVelocityKMH() < 10 then
|
||||
self:Load( Helicopter:GetPointVec2() )
|
||||
--self:Load( Helicopter:GetPointVec2() )
|
||||
self:Load()
|
||||
self.RoutePickup = false
|
||||
self.Relocating = true
|
||||
end
|
||||
@ -372,24 +388,30 @@ function AI_CARGO_HELICOPTER:onbeforeLoad( Helicopter, From, Event, To)
|
||||
self.BoardingCount = 0
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
self.Helicopter_Cargo = {}
|
||||
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
|
||||
local HelicopterUnit = HelicopterUnit -- Wrapper.Unit#UNIT
|
||||
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
self:F( { IsUnLoaded = Cargo:IsUnLoaded() } )
|
||||
if Cargo:IsUnLoaded() then
|
||||
if Cargo:IsUnLoaded() and not Cargo:IsDeployed() then
|
||||
if Cargo:IsInLoadRadius( HelicopterUnit:GetCoordinate() ) then
|
||||
self:F( { "In radius", HelicopterUnit:GetName() } )
|
||||
--Cargo:Ungroup()
|
||||
Cargo:Board( HelicopterUnit, 25 )
|
||||
self:__Board( 1, Cargo )
|
||||
Boarding = true
|
||||
|
||||
-- So now this APCUnit has Cargo that is being loaded.
|
||||
-- This will be used further in the logic to follow and to check cargo status.
|
||||
self.Helicopter_Cargo[HelicopterUnit] = Cargo
|
||||
break
|
||||
local CargoBayFreeWeight = HelicopterUnit:GetCargoBayFreeWeight()
|
||||
local CargoWeight = Cargo:GetWeight()
|
||||
|
||||
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
|
||||
|
||||
-- Only when there is space within the bay to load the next cargo item!
|
||||
if CargoBayFreeWeight > CargoWeight then --and CargoBayFreeVolume > CargoVolume then
|
||||
|
||||
--Cargo:Ungroup()
|
||||
Cargo:Board( HelicopterUnit, 25 )
|
||||
self:__Board( 1, Cargo )
|
||||
self.Helicopter_Cargo[HelicopterUnit] = Cargo
|
||||
Boarding = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -416,13 +438,65 @@ function AI_CARGO_HELICOPTER:onafterBoard( Helicopter, From, Event, To, Cargo )
|
||||
if not Cargo:IsLoaded() then
|
||||
self:__Board( 10, Cargo )
|
||||
else
|
||||
self:__Loaded( 1, Cargo )
|
||||
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
|
||||
local HelicopterUnit = HelicopterUnit -- Wrapper.Unit#UNIT
|
||||
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
if Cargo:IsUnLoaded() then
|
||||
if Cargo:IsInLoadRadius( HelicopterUnit:GetCoordinate() ) then
|
||||
local CargoBayFreeWeight = HelicopterUnit:GetCargoBayFreeWeight()
|
||||
local CargoWeight = Cargo:GetWeight()
|
||||
|
||||
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
|
||||
|
||||
-- Only when there is space within the bay to load the next cargo item!
|
||||
if CargoBayFreeWeight > CargoWeight then --and CargoBayFreeVolume > CargoVolume then
|
||||
Cargo:Board( HelicopterUnit, 25 )
|
||||
self:__Board( 10, Cargo )
|
||||
self.Helicopter_Cargo[HelicopterUnit] = Cargo
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
self:__Loaded( 1, Cargo ) -- Will only be executed when no more cargo is boarded.
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On before Land event.
|
||||
|
||||
--- On before Loaded event.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @return #boolean Cargo loaded.
|
||||
function AI_CARGO_HELICOPTER:onbeforeLoaded( Helicopter, From, Event, To, Cargo )
|
||||
self:F( { Helicopter, From, Event, To } )
|
||||
|
||||
local Loaded = true
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
for HelicopterUnit, Cargo in pairs( self.Helicopter_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
self:F( { IsLoaded = Cargo:IsLoaded(), IsDestroyed = Cargo:IsDestroyed(), Cargo:GetName(), Helicopter:GetName() } )
|
||||
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
|
||||
Loaded = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Loaded
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--- On after Loaded event. Check if cargo is loaded.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
-- @param #string From From state.
|
||||
@ -430,24 +504,12 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param Cargo.Cargo#CARGO Cargo Cargo object.
|
||||
-- @return #boolean Cargo is loaded.
|
||||
function AI_CARGO_HELICOPTER:onbeforeLoaded( Helicopter, From, Event, To, Cargo )
|
||||
function AI_CARGO_HELICOPTER:onafterLoaded( Helicopter, From, Event, To, Cargo )
|
||||
self:F( { Helicopter, From, Event, To, Cargo } )
|
||||
|
||||
local Loaded = true
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
for HelicopterUnit, Cargo in pairs( self.Helicopter_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
self:F( { IsLoaded = Cargo:IsLoaded(), IsDestroyed = Cargo:IsDestroyed() } )
|
||||
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
|
||||
Loaded = false
|
||||
end
|
||||
end
|
||||
|
||||
self.Transporting = true
|
||||
end
|
||||
|
||||
return Loaded
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -463,9 +525,11 @@ function AI_CARGO_HELICOPTER:onafterUnload( Helicopter, From, Event, To, Deploye
|
||||
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
|
||||
local HelicopterUnit = HelicopterUnit -- Wrapper.Unit#UNIT
|
||||
for _, Cargo in pairs( HelicopterUnit:GetCargo() ) do
|
||||
Cargo:UnBoard()
|
||||
Cargo:SetDeployed( true )
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
if Cargo:IsLoaded() then
|
||||
Cargo:UnBoard()
|
||||
Cargo:SetDeployed( true )
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -487,6 +551,17 @@ function AI_CARGO_HELICOPTER:onafterUnboard( Helicopter, From, Event, To, Cargo,
|
||||
if not Cargo:IsUnLoaded() then
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
else
|
||||
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
|
||||
local HelicopterUnit = HelicopterUnit -- Wrapper.Unit#UNIT
|
||||
for _, Cargo in pairs( HelicopterUnit:GetCargo() ) do
|
||||
if Cargo:IsLoaded() then
|
||||
Cargo:UnBoard()
|
||||
Cargo:SetDeployed( true )
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
self:__Unloaded( 1, Cargo, Deployed )
|
||||
end
|
||||
end
|
||||
@ -511,21 +586,16 @@ function AI_CARGO_HELICOPTER:onbeforeUnloaded( Helicopter, From, Event, To, Carg
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
|
||||
local CargoCheck = self.Helicopter_Cargo[HelicopterUnit] -- Cargo.Cargo#CARGO
|
||||
if CargoCheck then
|
||||
self:F( { CargoCheck:GetName(), IsUnLoaded = CargoCheck:IsUnLoaded() } )
|
||||
if CargoCheck:IsUnLoaded() == false then
|
||||
local IsEmpty = HelicopterUnit:IsCargoEmpty()
|
||||
self:I({ IsEmpty = IsEmpty })
|
||||
if not IsEmpty then
|
||||
AllUnloaded = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if AllUnloaded == true then
|
||||
if Deployed == true then
|
||||
for HelicopterUnit, Cargo in pairs( self.Helicopter_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
end
|
||||
self.Helicopter_Cargo = {}
|
||||
end
|
||||
self.Helicopter = Helicopter
|
||||
@ -632,11 +702,11 @@ end
|
||||
|
||||
--- On after Deploy event.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
-- @param Wrapper.Group#GROUP Helicopter Transport helicopter.
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which the cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordinate, Speed )
|
||||
|
||||
|
||||
@ -779,7 +779,8 @@ do -- CARGO
|
||||
|
||||
local Distance = 0
|
||||
if self:IsUnLoaded() then
|
||||
Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() )
|
||||
local CargoCoordinate = self.CargoObject:GetCoordinate()
|
||||
Distance = Coordinate:Get2DDistance( CargoCoordinate )
|
||||
self:T( Distance )
|
||||
if Distance <= self.LoadRadius then
|
||||
return true
|
||||
@ -810,7 +811,7 @@ do -- CARGO
|
||||
end
|
||||
|
||||
|
||||
--- Check if CargoCarrier is near the Cargo to be Loaded.
|
||||
--- Check if CargoCarrier is near the coordinate within NearRadius.
|
||||
-- @param #CARGO self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision).
|
||||
@ -875,6 +876,13 @@ do -- CARGO
|
||||
return self.CargoObject:GetCoordinate()
|
||||
end
|
||||
|
||||
--- Get the weight of the cargo.
|
||||
-- @param #CARGO self
|
||||
-- @return #number Weight The weight in kg.
|
||||
function CARGO:GetWeight()
|
||||
return self.Weight
|
||||
end
|
||||
|
||||
--- Set the weight of the cargo.
|
||||
-- @param #CARGO self
|
||||
-- @param #number Weight The weight in kg.
|
||||
@ -884,6 +892,22 @@ do -- CARGO
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get the volume of the cargo.
|
||||
-- @param #CARGO self
|
||||
-- @return #number Volume The volume in kg.
|
||||
function CARGO:GetVolume()
|
||||
return self.Volume
|
||||
end
|
||||
|
||||
--- Set the volume of the cargo.
|
||||
-- @param #CARGO self
|
||||
-- @param #number Volume The volume in kg.
|
||||
-- @return #CARGO
|
||||
function CARGO:SetVolume( Volume )
|
||||
self.Volume = Volume
|
||||
return self
|
||||
end
|
||||
|
||||
--- Send a CC message to a @{Wrapper.Group}.
|
||||
-- @param #CARGO self
|
||||
-- @param #string Message
|
||||
@ -997,13 +1021,27 @@ do -- CARGO_REPRESENTABLE
|
||||
-- @param #CARGO_REPRESENTABLE self
|
||||
-- @param #string Type
|
||||
-- @param #string Name
|
||||
-- @param #number Weight
|
||||
-- @param #number LoadRadius (optional)
|
||||
-- @param #number NearRadius (optional)
|
||||
-- @return #CARGO_REPRESENTABLE
|
||||
function CARGO_REPRESENTABLE:New( CargoObject, Type, Name, Weight, LoadRadius, NearRadius )
|
||||
local self = BASE:Inherit( self, CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE
|
||||
self:F( { Type, Name, Weight, LoadRadius, NearRadius } )
|
||||
function CARGO_REPRESENTABLE:New( CargoObject, Type, Name, LoadRadius, NearRadius )
|
||||
local self = BASE:Inherit( self, CARGO:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE
|
||||
self:F( { Type, Name, LoadRadius, NearRadius } )
|
||||
|
||||
local Desc = CargoObject:GetDesc()
|
||||
self:I( { Desc = Desc } )
|
||||
local Weight = math.random( 80, 120 )
|
||||
if Desc then
|
||||
Weight = Desc.massEmpty
|
||||
end
|
||||
|
||||
self:SetWeight( Weight )
|
||||
|
||||
-- local Box = CargoUnit:GetBoundingBox()
|
||||
-- local VolumeUnit = ( Box.max.x - Box.min.x ) * ( Box.max.y - Box.min.y ) * ( Box.max.z - Box.min.z )
|
||||
-- self:I( { VolumeUnit = VolumeUnit, WeightUnit = WeightUnit } )
|
||||
--self:SetVolume( VolumeUnit )
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
@ -1203,6 +1241,10 @@ end
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number Speed
|
||||
-- @param #number BoardDistance
|
||||
-- @param #number LoadDistance
|
||||
-- @param #number Angle
|
||||
function CARGO_PACKAGE:onafterOnBoarded( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle )
|
||||
self:F()
|
||||
|
||||
@ -1218,6 +1260,7 @@ end
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number Speed
|
||||
-- @param #number UnLoadDistance
|
||||
-- @param #number UnBoardDistance
|
||||
@ -1261,6 +1304,7 @@ end
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number Speed
|
||||
function CARGO_PACKAGE:onafterUnBoarded( From, Event, To, CargoCarrier, Speed )
|
||||
self:F()
|
||||
|
||||
@ -1304,6 +1348,8 @@ end
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number Speed
|
||||
-- @param #number Distance
|
||||
-- @param #number Angle
|
||||
function CARGO_PACKAGE:onafterUnLoad( From, Event, To, CargoCarrier, Speed, Distance, Angle )
|
||||
|
||||
@ -61,8 +61,8 @@ do -- CARGO_GROUP
|
||||
-- @param #number LoadRadius (optional) Distance in meters until which a cargo is loaded into the carrier. Cargo outside this radius has to be routed by other means to within the radius to be loaded.
|
||||
-- @param #number NearRadius (optional) Once the units are within this radius of the carrier, they are actually loaded, i.e. disappear from the scene.
|
||||
-- @return #CARGO_GROUP Cargo group object.
|
||||
function CARGO_GROUP:New( CargoGroup, Type, Name, LoadRadius )
|
||||
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( Type, Name, 0, LoadRadius ) ) -- #CARGO_GROUP
|
||||
function CARGO_GROUP:New( CargoGroup, Type, Name, LoadRadius, NearRadius )
|
||||
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_GROUP
|
||||
self:F( { Type, Name, LoadRadius } )
|
||||
|
||||
self.CargoSet = SET_CARGO:New()
|
||||
@ -73,6 +73,7 @@ do -- CARGO_GROUP
|
||||
self:SetDeployed( false )
|
||||
|
||||
local WeightGroup = 0
|
||||
local VolumeGroup = 0
|
||||
|
||||
self.CargoGroup:Destroy()
|
||||
|
||||
@ -96,20 +97,29 @@ do -- CARGO_GROUP
|
||||
|
||||
-- And we register the spawned unit as part of the CargoSet.
|
||||
local Unit = UNIT:Register( CargoUnitName )
|
||||
--local WeightUnit = Unit:GetDesc().massEmpty
|
||||
--WeightGroup = WeightGroup + WeightUnit
|
||||
local CargoUnit = CARGO_UNIT:New( Unit, Type, CargoUnitName, 10 )
|
||||
self.CargoSet:Add( CargoUnitName, CargoUnit )
|
||||
|
||||
end
|
||||
|
||||
-- Then we register the new group in the database
|
||||
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID)
|
||||
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID )
|
||||
|
||||
-- Now we spawn the new group based on the template created.
|
||||
self.CargoObject = _DATABASE:Spawn( GroupTemplate )
|
||||
|
||||
for CargoUnitID, CargoUnit in pairs( self.CargoObject:GetUnits() ) do
|
||||
|
||||
|
||||
local CargoUnitName = CargoUnit:GetName()
|
||||
|
||||
local Cargo = CARGO_UNIT:New( CargoUnit, Type, CargoUnitName, LoadRadius, NearRadius )
|
||||
self.CargoSet:Add( CargoUnitName, Cargo )
|
||||
|
||||
WeightGroup = WeightGroup + Cargo:GetWeight()
|
||||
--VolumeGroup = VolumeGroup + VolumeUnit
|
||||
|
||||
end
|
||||
|
||||
self:SetWeight( WeightGroup )
|
||||
self.CargoLimit = 10
|
||||
|
||||
self:T( { "Weight Cargo", WeightGroup } )
|
||||
|
||||
@ -257,10 +267,11 @@ do -- CARGO_GROUP
|
||||
|
||||
--- Enter Boarding State.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||
function CARGO_GROUP:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||
--self:F( { CargoCarrier.UnitName, From, Event, To } )
|
||||
|
||||
@ -304,10 +315,11 @@ do -- CARGO_GROUP
|
||||
|
||||
--- Leave Boarding State.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||
function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||
--self:F( { CargoCarrier.UnitName, From, Event, To } )
|
||||
|
||||
@ -359,10 +371,11 @@ do -- CARGO_GROUP
|
||||
|
||||
--- Enter UnBoarding State.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||
function CARGO_GROUP:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||
self:F( {From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
@ -401,10 +414,11 @@ do -- CARGO_GROUP
|
||||
|
||||
--- Leave UnBoarding State.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||
function CARGO_GROUP:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||
--self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
@ -438,10 +452,11 @@ do -- CARGO_GROUP
|
||||
|
||||
--- UnBoard Event.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||
function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||
--self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
@ -454,10 +469,10 @@ do -- CARGO_GROUP
|
||||
|
||||
--- Enter UnLoaded State.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Core.Point#POINT_VEC2
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2
|
||||
function CARGO_GROUP:onenterUnLoaded( From, Event, To, ToPointVec2, ... )
|
||||
--self:F( { From, Event, To, ToPointVec2 } )
|
||||
|
||||
@ -467,7 +482,7 @@ do -- CARGO_GROUP
|
||||
self.CargoSet:ForEach(
|
||||
function( Cargo )
|
||||
--Cargo:UnLoad( ToPointVec2 )
|
||||
local RandomVec2=ToPointVec2:GetRandomPointVec2InRadius(10)
|
||||
local RandomVec2=ToPointVec2:GetRandomPointVec2InRadius(20, 10)
|
||||
Cargo:UnLoad( RandomVec2 )
|
||||
end
|
||||
)
|
||||
@ -485,8 +500,6 @@ do -- CARGO_GROUP
|
||||
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
|
||||
-- @return #nil There is no valid Cargo in the CargoGroup.
|
||||
function CARGO_GROUP:GetCoordinate()
|
||||
self:F()
|
||||
|
||||
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
||||
|
||||
if Cargo then
|
||||
@ -592,8 +605,7 @@ do -- CARGO_GROUP
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Wrapper.Group#GROUP CargoCarrier
|
||||
-- @param #number NearRadius
|
||||
-- @return #boolean The Cargo is near to the Carrier.
|
||||
-- @return #nil The Cargo is not near to the Carrier.
|
||||
-- @return #boolean The Cargo is near to the Carrier or #nil if the Cargo is not near to the Carrier.
|
||||
function CARGO_GROUP:IsNear( CargoCarrier, NearRadius )
|
||||
self:F( {NearRadius = NearRadius } )
|
||||
|
||||
@ -621,12 +633,19 @@ do -- CARGO_GROUP
|
||||
|
||||
if Cargo then
|
||||
local Distance = 0
|
||||
local CargoCoordinate
|
||||
if Cargo:IsLoaded() then
|
||||
Distance = Coordinate:Get2DDistance( Cargo.CargoCarrier:GetCoordinate() )
|
||||
CargoCoordinate = Cargo.CargoCarrier:GetCoordinate()
|
||||
else
|
||||
Distance = Coordinate:Get2DDistance( Cargo.CargoObject:GetCoordinate() )
|
||||
CargoCoordinate = Cargo.CargoObject:GetCoordinate()
|
||||
end
|
||||
|
||||
-- if CargoCoordinate then
|
||||
Distance = Coordinate:Get2DDistance( CargoCoordinate )
|
||||
-- else
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
self:F( { Distance = Distance, LoadRadius = self.LoadRadius } )
|
||||
if Distance <= self.LoadRadius then
|
||||
return true
|
||||
|
||||
@ -42,9 +42,9 @@ do -- CARGO_UNIT
|
||||
-- @param #number LoadRadius (optional)
|
||||
-- @param #number NearRadius (optional)
|
||||
-- @return #CARGO_UNIT
|
||||
function CARGO_UNIT:New( CargoUnit, Type, Name, Weight, NearRadius )
|
||||
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoUnit, Type, Name, Weight, NearRadius ) ) -- #CARGO_UNIT
|
||||
self:I( { Type, Name, Weight, NearRadius } )
|
||||
function CARGO_UNIT:New( CargoUnit, Type, Name, LoadRadius, NearRadius )
|
||||
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoUnit, Type, Name, LoadRadius, NearRadius ) ) -- #CARGO_UNIT
|
||||
self:I( { Type, Name, LoadRadius, NearRadius } )
|
||||
|
||||
self:T( CargoUnit )
|
||||
self.CargoObject = CargoUnit
|
||||
@ -62,6 +62,7 @@ do -- CARGO_UNIT
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius (optional) Defaut 25 m.
|
||||
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
@ -131,6 +132,7 @@ do -- CARGO_UNIT
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
@ -158,6 +160,7 @@ do -- CARGO_UNIT
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
@ -223,8 +226,6 @@ do -- CARGO_UNIT
|
||||
function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||
self:F( { From, Event, To, CargoCarrier, NearRadius } )
|
||||
|
||||
local NearRadius = NearRadius or 25
|
||||
|
||||
self.CargoInAir = self.CargoObject:InAir()
|
||||
|
||||
local Desc = self.CargoObject:GetDesc()
|
||||
@ -236,6 +237,9 @@ do -- CARGO_UNIT
|
||||
-- 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
|
||||
-- If NearRadius is given, then use the given NearRadius, otherwise calculate the NearRadius
|
||||
-- based upon the Carrier bounding radius, which is calculated from the bounding rectangle on the Y axis.
|
||||
local NearRadius = CargoCarrier:GetBoundingRadius( NearRadius )
|
||||
if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then
|
||||
self:Load( CargoCarrier, NearRadius, ... )
|
||||
else
|
||||
@ -247,8 +251,6 @@ do -- CARGO_UNIT
|
||||
local Angle = 180
|
||||
local Distance = 5
|
||||
|
||||
NearRadius = NearRadius or 25
|
||||
|
||||
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
|
||||
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
||||
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
|
||||
@ -281,7 +283,7 @@ do -- CARGO_UNIT
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Client#CLIENT CargoCarrier
|
||||
-- @param #number NearRadius
|
||||
-- @param #number NearRadius Default 25 m.
|
||||
function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||
--self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } )
|
||||
|
||||
@ -299,8 +301,6 @@ do -- CARGO_UNIT
|
||||
local Angle = 180
|
||||
local Distance = 5
|
||||
|
||||
NearRadius = NearRadius or 25
|
||||
|
||||
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
|
||||
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
||||
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
|
||||
@ -338,6 +338,7 @@ do -- CARGO_UNIT
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number NearRadius Default 25 m.
|
||||
function CARGO_UNIT:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||
--self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } )
|
||||
|
||||
@ -345,8 +346,6 @@ do -- CARGO_UNIT
|
||||
local Angle = 180
|
||||
local Distance = 5
|
||||
|
||||
local NearRadius = NearRadius or 25
|
||||
|
||||
if From == "UnLoaded" or From == "Boarding" then
|
||||
|
||||
end
|
||||
|
||||
@ -799,7 +799,6 @@ end
|
||||
-- @param Key The key that is used as a reference of the value. Note that the key can be a #string, but it can also be any other type!
|
||||
-- @param Value The value to is stored in the object.
|
||||
-- @return The Value set.
|
||||
-- @return #nil The Key was not found and thus the Value could not be retrieved.
|
||||
function BASE:SetState( Object, Key, Value )
|
||||
|
||||
local ClassNameAndID = Object:GetClassNameAndID()
|
||||
@ -816,7 +815,7 @@ end
|
||||
-- @param #BASE self
|
||||
-- @param Object The object that holds the Value set by the Key.
|
||||
-- @param Key The key that is used to retrieve the value. Note that the key can be a #string, but it can also be any other type!
|
||||
-- @return The Value retrieved.
|
||||
-- @return The Value retrieved or nil if the Key was not found and thus the Value could not be retrieved.
|
||||
function BASE:GetState( Object, Key )
|
||||
|
||||
local ClassNameAndID = Object:GetClassNameAndID()
|
||||
@ -829,6 +828,10 @@ function BASE:GetState( Object, Key )
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Clear the state of an object.
|
||||
-- @param #BASE self
|
||||
-- @param Object The object that holds the Value set by the Key.
|
||||
-- @param StateName The key that is should be cleared.
|
||||
function BASE:ClearState( Object, StateName )
|
||||
|
||||
local ClassNameAndID = Object:GetClassNameAndID()
|
||||
|
||||
@ -374,14 +374,15 @@ do -- cargo
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:_RegisterCargos()
|
||||
|
||||
local Groups = UTILS.DeepCopy( self.GROUPS ) -- This is a very important statement. CARGO_GROUP:New creates a new _DATABASE.GROUP entry, which will confuse the loop. I searched 4 hours on this to find the bug!
|
||||
|
||||
for CargoGroupName, CargoGroup in pairs( self.GROUPS ) do
|
||||
for CargoGroupName, CargoGroup in pairs( Groups ) do
|
||||
self:I( { Cargo = CargoGroupName } )
|
||||
if self:IsCargo( CargoGroupName ) then
|
||||
local CargoInfo = CargoGroupName:match("~CARGO(.*)")
|
||||
local CargoParam = CargoInfo and CargoInfo:match( "%((.*)%)")
|
||||
local CargoName1 = CargoGroupName:match("(.*)~CARGO%(.*%)")
|
||||
local CargoName2 = CargoGroupName:match(".*~CARGO%(.*%)(.*)")
|
||||
self:E({CargoName1 = CargoName1, CargoName2 = CargoName2 })
|
||||
local CargoName = CargoName1 .. ( CargoName2 or "" )
|
||||
local Type = CargoParam and CargoParam:match( "T=([%a%d ]+),?")
|
||||
local Name = CargoParam and CargoParam:match( "N=([%a%d]+),?") or CargoName
|
||||
@ -459,7 +460,7 @@ end
|
||||
function DATABASE:AddGroup( GroupName )
|
||||
|
||||
if not self.GROUPS[GroupName] then
|
||||
self:E( { "Add GROUP:", GroupName } )
|
||||
self:I( { "Add GROUP:", GroupName } )
|
||||
self.GROUPS[GroupName] = GROUP:Register( GroupName )
|
||||
end
|
||||
|
||||
@ -471,7 +472,7 @@ end
|
||||
function DATABASE:AddPlayer( UnitName, PlayerName )
|
||||
|
||||
if PlayerName then
|
||||
self:E( { "Add player for unit:", UnitName, PlayerName } )
|
||||
self:I( { "Add player for unit:", UnitName, PlayerName } )
|
||||
self.PLAYERS[PlayerName] = UnitName
|
||||
self.PLAYERUNITS[PlayerName] = self:FindUnit( UnitName )
|
||||
self.PLAYERSJOINED[PlayerName] = PlayerName
|
||||
@ -483,7 +484,7 @@ end
|
||||
function DATABASE:DeletePlayer( UnitName, PlayerName )
|
||||
|
||||
if PlayerName then
|
||||
self:E( { "Clean player:", PlayerName } )
|
||||
self:I( { "Clean player:", PlayerName } )
|
||||
self.PLAYERS[PlayerName] = nil
|
||||
self.PLAYERUNITS[PlayerName] = nil
|
||||
end
|
||||
@ -750,7 +751,7 @@ function DATABASE:_RegisterPlayers()
|
||||
local UnitName = UnitData:getName()
|
||||
local PlayerName = UnitData:getPlayerName()
|
||||
if not self.PLAYERS[PlayerName] then
|
||||
self:E( { "Add player for unit:", UnitName, PlayerName } )
|
||||
self:I( { "Add player for unit:", UnitName, PlayerName } )
|
||||
self:AddPlayer( UnitName, PlayerName )
|
||||
end
|
||||
end
|
||||
@ -773,13 +774,13 @@ function DATABASE:_RegisterGroupsAndUnits()
|
||||
if DCSGroup:isExist() then
|
||||
local DCSGroupName = DCSGroup:getName()
|
||||
|
||||
self:E( { "Register Group:", DCSGroupName } )
|
||||
self:I( { "Register Group:", DCSGroupName } )
|
||||
self:AddGroup( DCSGroupName )
|
||||
|
||||
for DCSUnitId, DCSUnit in pairs( DCSGroup:getUnits() ) do
|
||||
|
||||
local DCSUnitName = DCSUnit:getName()
|
||||
self:E( { "Register Unit:", DCSUnitName } )
|
||||
self:I( { "Register Unit:", DCSUnitName } )
|
||||
self:AddUnit( DCSUnitName )
|
||||
end
|
||||
else
|
||||
@ -789,6 +790,11 @@ function DATABASE:_RegisterGroupsAndUnits()
|
||||
end
|
||||
end
|
||||
|
||||
self:I("Groups:")
|
||||
for GroupName, Group in pairs( self.GROUPS ) do
|
||||
self:I( { "Group:", GroupName } )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@ -798,7 +804,7 @@ end
|
||||
function DATABASE:_RegisterClients()
|
||||
|
||||
for ClientName, ClientTemplate in pairs( self.Templates.ClientsByName ) do
|
||||
self:E( { "Register Client:", ClientName } )
|
||||
self:I( { "Register Client:", ClientName } )
|
||||
self:AddClient( ClientName )
|
||||
end
|
||||
|
||||
@ -809,14 +815,14 @@ end
|
||||
function DATABASE:_RegisterStatics()
|
||||
|
||||
local CoalitionsData = { GroupsRed = coalition.getStaticObjects( coalition.side.RED ), GroupsBlue = coalition.getStaticObjects( coalition.side.BLUE ) }
|
||||
self:E( { Statics = CoalitionsData } )
|
||||
self:I( { Statics = CoalitionsData } )
|
||||
for CoalitionId, CoalitionData in pairs( CoalitionsData ) do
|
||||
for DCSStaticId, DCSStatic in pairs( CoalitionData ) do
|
||||
|
||||
if DCSStatic:isExist() then
|
||||
local DCSStaticName = DCSStatic:getName()
|
||||
|
||||
self:E( { "Register Static:", DCSStaticName } )
|
||||
self:I( { "Register Static:", DCSStaticName } )
|
||||
self:AddStatic( DCSStaticName )
|
||||
else
|
||||
self:E( { "Static does not exist: ", DCSStatic } )
|
||||
@ -836,7 +842,7 @@ function DATABASE:_RegisterAirbases()
|
||||
|
||||
local DCSAirbaseName = DCSAirbase:getName()
|
||||
|
||||
self:E( { "Register Airbase:", DCSAirbaseName, DCSAirbase:getID() } )
|
||||
self:I( { "Register Airbase:", DCSAirbaseName, DCSAirbase:getID() } )
|
||||
self:AddAirbase( DCSAirbaseName )
|
||||
end
|
||||
end
|
||||
@ -866,9 +872,8 @@ function DATABASE:_EventOnBirth( Event )
|
||||
Event.IniUnit = self:FindUnit( Event.IniDCSUnitName )
|
||||
Event.IniGroup = self:FindGroup( Event.IniDCSGroupName )
|
||||
local PlayerName = Event.IniUnit:GetPlayerName()
|
||||
self:E( { "PlayerName:", PlayerName } )
|
||||
if PlayerName then
|
||||
self:E( { "Player Joined:", PlayerName } )
|
||||
self:I( { "Player Joined:", PlayerName } )
|
||||
if not self.PLAYERS[PlayerName] then
|
||||
self:AddPlayer( Event.IniUnitName, PlayerName )
|
||||
end
|
||||
@ -937,7 +942,7 @@ function DATABASE:_EventOnPlayerLeaveUnit( Event )
|
||||
if Event.IniObjectCategory == 1 then
|
||||
local PlayerName = Event.IniUnit:GetPlayerName()
|
||||
if PlayerName and self.PLAYERS[PlayerName] then
|
||||
self:E( { "Player Left:", PlayerName } )
|
||||
self:I( { "Player Left:", PlayerName } )
|
||||
local Settings = SETTINGS:Set( PlayerName )
|
||||
Settings:RemovePlayerMenu( Event.IniUnit )
|
||||
self:DeletePlayer( Event.IniUnit, PlayerName )
|
||||
|
||||
@ -719,7 +719,7 @@ do -- Event Creation
|
||||
-- @param #EVENT self
|
||||
-- @param AI.AI_Cargo#AI_CARGO Cargo The Cargo created.
|
||||
function EVENT:CreateEventNewCargo( Cargo )
|
||||
self:F( { Cargo } )
|
||||
self:I( { Cargo } )
|
||||
|
||||
local Event = {
|
||||
id = EVENTS.NewCargo,
|
||||
|
||||
@ -308,7 +308,7 @@ end
|
||||
|
||||
--- Sends a MESSAGE to all players.
|
||||
-- @param #MESSAGE self
|
||||
-- @param Core.Settings#Settings (Optional) Settings for message display
|
||||
-- @param Core.Settings#Settings Settings (Optional) Settings for message display.
|
||||
-- @return #MESSAGE
|
||||
-- @usage
|
||||
-- -- Send a message created to all players.
|
||||
|
||||
@ -1096,6 +1096,37 @@ do -- COORDINATE
|
||||
return RoutePoint
|
||||
end
|
||||
|
||||
--- Gets the nearest airbase with respect to the current coordinates.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number AirbaseCategory Category of the airbase.
|
||||
-- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate.
|
||||
-- @return #number Distance to the closest airbase in meters.
|
||||
function COORDINATE:GetClosestAirbase(AirbaseCategory)
|
||||
local airbases=AIRBASE.GetAllAirbases()
|
||||
|
||||
local closest=nil
|
||||
local distmin=nil
|
||||
-- Loop over all airbases.
|
||||
for _,_airbase in pairs(airbases) do
|
||||
local airbase=_airbase --Wrapper.Airbase#AIRBASE
|
||||
local category=airbase:GetDesc().category
|
||||
if AirbaseCategory and AirbaseCategory==category or AirbaseCategory==nil then
|
||||
local dist=self:Get2DDistance(airbase:GetCoordinate())
|
||||
if closest==nil then
|
||||
distmin=dist
|
||||
closest=airbase
|
||||
else
|
||||
if dist<distmin then
|
||||
distmin=dist
|
||||
closest=airbase
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return closest,distmin
|
||||
end
|
||||
|
||||
--- Gets the nearest parking spot.
|
||||
-- @param #COORDINATE self
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase (Optional) Search only parking spots at this airbase.
|
||||
@ -1183,18 +1214,26 @@ do -- COORDINATE
|
||||
return COORDINATE:NewFromVec2(vec2)
|
||||
end
|
||||
|
||||
--- Returns a table of coordinates to a destination using only roads.
|
||||
|
||||
--- Returns a table of coordinates to a destination using only roads or railroads.
|
||||
-- The first point is the closest point on road of the given coordinate.
|
||||
-- By default, the last point is the closest point on road of the ToCoord. Hence, the coordinate itself and the final ToCoord are not necessarily included in the path.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #COORDINATE ToCoord Coordinate of destination.
|
||||
-- @param #boolean IncludeEndpoints (Optional) Include the coordinate itself and the ToCoordinate in the path.
|
||||
-- @param #boolean Railroad (Optional) If true, path on railroad is returned. Default false.
|
||||
-- @return #table Table of coordinates on road. If no path on road can be found, nil is returned or just the endpoints.
|
||||
-- @return #number The length of the total path.
|
||||
function COORDINATE:GetPathOnRoad(ToCoord, IncludeEndpoints)
|
||||
function COORDINATE:GetPathOnRoad(ToCoord, IncludeEndpoints, Railroad)
|
||||
|
||||
-- Set road type.
|
||||
local RoadType="roads"
|
||||
if Railroad==true then
|
||||
RoadType="railroads"
|
||||
end
|
||||
|
||||
-- DCS API function returning a table of vec2.
|
||||
local path = land.findPathOnRoads("roads", self.x, self.z, ToCoord.x, ToCoord.z)
|
||||
local path = land.findPathOnRoads(RoadType, self.x, self.z, ToCoord.x, ToCoord.z)
|
||||
|
||||
-- Array holding the path coordinates.
|
||||
local Path={}
|
||||
|
||||
@ -809,6 +809,16 @@ function SET_GROUP:GetAliveSet()
|
||||
return AliveSet.Set or {}
|
||||
end
|
||||
|
||||
--- Add a GROUP to SET_GROUP.
|
||||
-- @param Core.Set#SET_GROUP self
|
||||
-- @param Wrapper.Group#GROUP group The group which should be added to the set.
|
||||
-- @return self
|
||||
function SET_GROUP:AddGroup( group )
|
||||
|
||||
self:Add( group:GetName(), group )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add GROUP(s) to SET_GROUP.
|
||||
-- @param Core.Set#SET_GROUP self
|
||||
@ -3968,6 +3978,17 @@ function SET_AIRBASE:New()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add an AIRBASE object to SET_AIRBASE.
|
||||
-- @param Core.Set#SET_AIRBASE self
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase Airbase that should be added to the set.
|
||||
-- @return self
|
||||
function SET_AIRBASE:AddAirbase( airbase )
|
||||
|
||||
self:Add( airbase:GetName(), airbase )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add AIRBASEs to SET_AIRBASE.
|
||||
-- @param Core.Set#SET_AIRBASE self
|
||||
-- @param #string AddAirbaseNames A single name or an array of AIRBASE names.
|
||||
@ -4010,6 +4031,45 @@ function SET_AIRBASE:FindAirbase( AirbaseName )
|
||||
end
|
||||
|
||||
|
||||
--- Finds an Airbase in range of a coordinate.
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Range
|
||||
-- @return Wrapper.Airbase#AIRBASE The found Airbase.
|
||||
function SET_AIRBASE:FindAirbaseInRange( Coordinate, Range )
|
||||
|
||||
local AirbaseFound = nil
|
||||
|
||||
for AirbaseName, AirbaseObject in pairs( self.Set ) do
|
||||
|
||||
local AirbaseCoordinate = AirbaseObject:GetCoordinate()
|
||||
local Distance = Coordinate:Get2DDistance( AirbaseCoordinate )
|
||||
|
||||
self:F({Distance=Distance})
|
||||
|
||||
if Distance <= Range then
|
||||
AirbaseFound = AirbaseObject
|
||||
break
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return AirbaseFound
|
||||
end
|
||||
|
||||
|
||||
--- Finds a random Airbase in the set.
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @return Wrapper.Airbase#AIRBASE The found Airbase.
|
||||
function SET_AIRBASE:GetRandomAirbase()
|
||||
|
||||
local RandomAirbase = self:GetRandom()
|
||||
self:F( { RandomAirbase = RandomAirbase:GetName() } )
|
||||
|
||||
return RandomAirbase
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Builds a set of airbases of coalitions.
|
||||
-- Possible current coalitions are red, blue and neutral.
|
||||
|
||||
@ -81,11 +81,11 @@ do -- world
|
||||
|
||||
--- Searches a defined volume of 3d space for the specified objects within it and then can run function on each returned object. See [hoggit](https://wiki.hoggitworld.com/view/DCS_func_searchObjects).
|
||||
-- @function [parent=#world] searchObjects
|
||||
-- @param #DCS.Object.Category objectcategory Category (can be a table) of objects to search.
|
||||
-- @param #DCS word.VolumeType volume Shape of the search area/volume.
|
||||
-- @param #ObjectSeachHandler handler A function that handles the search.
|
||||
-- @param DCS#Object.Category objectcategory Category (can be a table) of objects to search.
|
||||
-- @param DCS#word.VolumeType volume Shape of the search area/volume.
|
||||
-- @param ObjectSeachHandler handler A function that handles the search.
|
||||
-- @param #table any Additional data.
|
||||
-- @return #DCS.unit
|
||||
-- @return DCS#Unit
|
||||
|
||||
--- Returns a table of mark panels indexed numerically that are present within the mission. See [hoggit](https://wiki.hoggitworld.com/view/DCS_func_getMarkPanels)
|
||||
-- @function [parent=#world] getMarkPanels
|
||||
@ -959,6 +959,7 @@ do -- Group
|
||||
-- @field HELICOPTER
|
||||
-- @field GROUND
|
||||
-- @field SHIP
|
||||
-- @field TRAIN
|
||||
|
||||
-- Static Functions
|
||||
|
||||
|
||||
@ -515,6 +515,7 @@ do -- DETECTION_BASE
|
||||
|
||||
for DetectionGroupID, DetectionGroupData in pairs( self.DetectionSetGroup:GetSet() ) do
|
||||
--self:F( { DetectionGroupData } )
|
||||
self:F( {"FF", DetectionGroupData } )
|
||||
self:__DetectionGroup( DetectDelay, DetectionGroupData, DetectionTimeStamp ) -- Process each detection asynchronously.
|
||||
self.DetectionCount = self.DetectionCount + 1
|
||||
DetectDelay = DetectDelay + 1
|
||||
@ -1877,7 +1878,7 @@ do -- DETECTION_UNITS
|
||||
-- @param #DETECTION_UNITS self
|
||||
-- @return #DETECTION_UNITS self
|
||||
function DETECTION_UNITS:CreateDetectionItems()
|
||||
|
||||
env.info("FF createdetectionitmes")
|
||||
-- Loop the current detected items, and check if each object still exists and is detected.
|
||||
|
||||
for DetectedItemKey, DetectedItem in pairs( self.DetectedItems ) do
|
||||
|
||||
@ -1,172 +0,0 @@
|
||||
--- **Functional** - (R2.4) JTAC
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- JTAC mimic
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Feature 1
|
||||
-- * Feature 2
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # Demo Missions
|
||||
--
|
||||
-- ### [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS)
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # YouTube Channel
|
||||
--
|
||||
-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)**
|
||||
--
|
||||
-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536)
|
||||
--
|
||||
-- ====
|
||||
-- @module Functional.Jtac
|
||||
-- @image JTAC.JPG
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--- JTAC class
|
||||
-- @type JTAC
|
||||
-- @field #string ClassName Name of the class.
|
||||
|
||||
--- Easy assignment of JTAC.
|
||||
--
|
||||
-- A new ARTY object can be created with the @{#ARTY.New}(*group*) contructor.
|
||||
-- The parameter *group* has to be a MOOSE Group object and defines ARTY group.
|
||||
--
|
||||
-- The ARTY FSM process can be started by the @{#ARTY.Start}() command.
|
||||
--
|
||||
-- ## The ARTY Process
|
||||
--
|
||||
-- 
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #JTAC
|
||||
JTAC={
|
||||
ClassName="JTAC",
|
||||
Debug=false,
|
||||
}
|
||||
|
||||
--- Some ID to identify who we are in output of the DCS.log file.
|
||||
-- @field #string id
|
||||
JTAC.id="JTAC | "
|
||||
|
||||
--- Arty script version.
|
||||
-- @field #string version
|
||||
JTAC.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO list:
|
||||
-- TODO: a lot.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Creates a new JTAC object.
|
||||
-- @param #JTAC self
|
||||
-- @param Wrapper.Group#GROUP group The GROUP object for which artillery tasks should be assigned.
|
||||
-- @param alias (Optional) Alias name the group will be calling itself when sending messages. Default is the group name.
|
||||
-- @return #JTAC JTAC object or nil if group does not exist or is not a ground or naval group.
|
||||
function JTAC:New(group, alias)
|
||||
BASE:F2(group)
|
||||
|
||||
-- Inherits from FSM_CONTROLLABLE
|
||||
local self=BASE:Inherit(self, FSM_CONTROLLABLE:New()) -- #JTAC
|
||||
|
||||
-- Check that group is present.
|
||||
if group then
|
||||
self:T(JTAC.id..string.format("JTAC script version %s. Added group %s.", JTAC.version, group:GetName()))
|
||||
else
|
||||
self:E(JTAC.id.."ERROR: Requested JTAC group does not exist! (Has to be a MOOSE group.)")
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Set the controllable for the FSM.
|
||||
self:SetControllable(group)
|
||||
|
||||
---------------
|
||||
-- Transitions:
|
||||
---------------
|
||||
|
||||
-- Entry.
|
||||
self:AddTransition("*", "Start", "Ready")
|
||||
self:AddTransition("Ready", "LaserOn", "Lasing")
|
||||
self:AddTransition("Lasing", "Lasing", "Lasing")
|
||||
self:AddTransition("Lasing", "LaserOff", "Ready")
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Start Event
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- After "Start" event.
|
||||
-- @param #JTAC self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function JTAC:onafterStart(Controllable, From, Event, To)
|
||||
--self:_EventFromTo("onafterStart", Event, From, To)
|
||||
|
||||
-- Debug output.
|
||||
local text=string.format("Started JTAC version %s for group %s.", JTAC.version, Controllable:GetName())
|
||||
self:E(JTAC.id..text)
|
||||
MESSAGE:New(text, 5):ToAllIf(self.Debug)
|
||||
|
||||
end
|
||||
|
||||
--- After "LaserOn" event.
|
||||
-- @param #JTAC self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Unit#UNIT Target Target that should be lased.
|
||||
function JTAC:onafterLaserOn(Controllable, From, Event, To, Target)
|
||||
--self:_EventFromTo("onafterStart", Event, From, To)
|
||||
|
||||
-- Debug output.
|
||||
local text=string.format("JTAC %s lasing target %s.", Controllable:GetName(), Target:GetName())
|
||||
self:E(JTAC.id..text)
|
||||
MESSAGE:New(text, 5):ToAllIf(self.Debug)
|
||||
|
||||
-- Start lasing.
|
||||
Controllable:LaseUnit(Target, self.LaserCode, self.Duration)
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- After "LaserOff" event.
|
||||
-- @param #JTAC self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function JTAC:onafterLaserOff(Controllable, From, Event, To)
|
||||
--self:_EventFromTo("onafterStart", Event, From, To)
|
||||
|
||||
-- Debug output.
|
||||
local text=string.format("JTAC %s stoped lasing.", Controllable:GetName())
|
||||
self:E(JTAC.id..text)
|
||||
MESSAGE:New(text, 5):ToAllIf(self.Debug)
|
||||
|
||||
-- Turn of laser.
|
||||
Controllable:LaseOff()
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -219,6 +219,44 @@
|
||||
-- Hence, the default flight plan for a RAT aircraft will be: Fly from airport A to B, get respawned at C and fly to D, get respawned at E and fly to F, ...
|
||||
-- This ensures that you always have a constant number of AI aircraft on your map.
|
||||
--
|
||||
-- ## Parking Problems
|
||||
--
|
||||
-- One big issue in DCS is that not all aircraft can be spawned on every airport or airbase. In particular, bigger aircraft might not have a valid parking spot at smaller airports and
|
||||
-- airstripes. This can lead to multiple problems in DCS.
|
||||
--
|
||||
-- * Landing: When an aircraft tries to land at an airport where it does not have a valid parking spot, it is immidiately despawned the moment its wheels touch the runway, i.e.
|
||||
-- when a landing event is triggered. This leads to the loss of the RAT aircraft. On possible way to circumvent the this problem is to let another RAT aircraft spawn at landing
|
||||
-- and not when it shuts down its engines. See the @{RAT.RespawnAfterLanding}() function.
|
||||
-- * Spawning: When a big aircraft is dynamically spawned on a small airbase a few things can go wrong. For example, it could be spawned at a parking spot with a shelter.
|
||||
-- Or it could be damaged by a scenery object when it is taxiing out to the runway, or it could overlap with other aircraft on parking spots near by.
|
||||
--
|
||||
-- You can check yourself if an aircraft has a valid parking spot at an airbase by dragging its group on the airport in the mission editor and set it to start from ramp.
|
||||
-- If it stays at the airport, it has a valid parking spot, if it jumps to another airport, it does not have a valid parking spot on that airbase.
|
||||
--
|
||||
-- ### Setting the Terminal Type
|
||||
-- Each parking spot has a specific type depending on its size or if a helicopter spot or a shelter etc. The classification is not perfect but it is the best we have.
|
||||
-- If you encounter problems described above, you can request a specific terminal type for the RAT aircraft. This can be done by the @{#RAT.SetTerminalType}(*terminaltype*)
|
||||
-- function. The parameter *terminaltype* can be set as follows
|
||||
--
|
||||
-- * AIRBASE.TerminalType.HelicopterOnly: Special spots for Helicopers.
|
||||
-- * AIRBASE.TerminalType.Shelter: Hardened Air Shelter. Currently only on Caucaus map.
|
||||
-- * AIRBASE.TerminalType.OpenMed: Open/Shelter air airplane only.
|
||||
-- * AIRBASE.TerminalType.OpenBig: Open air spawn points. Generally larger but does not guarantee large aircraft are capable of spawning there.
|
||||
-- * AIRBASE.TerminalType.OpenMedOrBig: Combines OpenMed and OpenBig spots.
|
||||
-- * AIRBASE.TerminalType.HelicopterUnsable: Combines HelicopterOnly, OpenMed and OpenBig.
|
||||
-- * AIRBASE.TerminalType.FighterAircraft: Combines Shelter, OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft.
|
||||
--
|
||||
-- So for example
|
||||
-- c17=RAT:New("C-17")
|
||||
-- c17:SetTerminalType(AIRBASE.TerminalType.OpenBig)
|
||||
-- c17:Spawn(5)
|
||||
--
|
||||
-- This would randomly spawn five C-17s but only on airports which have big open air parking spots. Note that also only destination airports are allowed
|
||||
-- which do have this type of parking spot. This should ensure that the aircraft is able to land at the destination without beeing despawned immidiately.
|
||||
--
|
||||
-- Also, the aircraft are spawned only on the requested parking spot types and not on any other type. If no parking spot of this type is availabe at the
|
||||
-- moment of spawning, the group is automatically spawned in air above the selected airport.
|
||||
--
|
||||
-- ## Examples
|
||||
--
|
||||
-- Here are a few examples, how you can modify the default settings of RAT class objects.
|
||||
@ -511,7 +549,7 @@ RAT.id="RAT | "
|
||||
--- RAT version.
|
||||
-- @list version
|
||||
RAT.version={
|
||||
version = "2.3.2",
|
||||
version = "2.3.3",
|
||||
print = true,
|
||||
}
|
||||
|
||||
@ -983,11 +1021,11 @@ function RAT:SetCoalitionAircraft(color)
|
||||
end
|
||||
|
||||
--- Set country of RAT group.
|
||||
-- See https://wiki.hoggitworld.com/view/DCS_enum_country
|
||||
-- See [DCS_enum_country](https://wiki.hoggitworld.com/view/DCS_enum_country).
|
||||
--
|
||||
-- This overrules the coalition settings. So if you want your group to be of a specific coalition, you have to set a country that is part of that coalition.
|
||||
-- @param #RAT self
|
||||
-- @param #DCS.country.id id DCS country enumerator ID. For example country.id.USA or country.id.RUSSIA.
|
||||
-- @param DCS#country.id id DCS country enumerator ID. For example country.id.USA or country.id.RUSSIA.
|
||||
-- @return #RAT RAT self object.
|
||||
function RAT:SetCountry(id)
|
||||
self:F2(id)
|
||||
@ -995,10 +1033,17 @@ function RAT:SetCountry(id)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the terminal type the aircraft use when spawning at an airbase. Cf. https://wiki.hoggitworld.com/view/DCS_func_getParking
|
||||
--- Set the terminal type the aircraft use when spawning at an airbase. See [DCS_func_getParking](https://wiki.hoggitworld.com/view/DCS_func_getParking).
|
||||
-- Note that some additional terminal types have been introduced. Check @{Wrapper.Airbase#AIRBASE} class for details.
|
||||
-- Also note that only airports which have this kind of terminal are possible departures and/or destinations.
|
||||
-- @param #RAT self
|
||||
-- @param Wrapper.Airbase#AIRBASE.TerminalType termtype Type of terminal. Use enumerator AIRBASE.TerminalType.XXX.
|
||||
-- @return #RAT RAT self object.
|
||||
--
|
||||
-- @usage
|
||||
-- c17=RAT:New("C-17 BIG Plane")
|
||||
-- c17:SetTerminalType(AIRBASE.TerminalType.OpenBig) -- Only very big parking spots are used.
|
||||
-- c17:Spawn(5)
|
||||
function RAT:SetTerminalType(termtype)
|
||||
self:F2(termtype)
|
||||
self.termtype=termtype
|
||||
@ -3010,14 +3055,27 @@ function RAT:_PickDeparture(takeoff)
|
||||
if self.random_departure then
|
||||
|
||||
-- Airports of friendly coalitions.
|
||||
for _,airport in pairs(self.airports) do
|
||||
for _,_airport in pairs(self.airports) do
|
||||
|
||||
local airport=_airport --Wrapper.Airbase#AIRBASE
|
||||
|
||||
local name=airport:GetName()
|
||||
if not self:_Excluded(name) then
|
||||
if takeoff==RAT.wp.air then
|
||||
|
||||
table.insert(departures, airport:GetZone()) -- insert zone object.
|
||||
|
||||
else
|
||||
table.insert(departures, airport) -- insert airport object.
|
||||
|
||||
-- Check if airbase has the right terminals.
|
||||
local nspots=1
|
||||
if self.termtype~=nil then
|
||||
nspots=airport:GetParkingSpotsNumber(self.termtype)
|
||||
end
|
||||
|
||||
if nspots>0 then
|
||||
table.insert(departures, airport) -- insert airport object.
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -3034,6 +3092,14 @@ function RAT:_PickDeparture(takeoff)
|
||||
dep=AIRBASE:FindByName(name):GetZone()
|
||||
else
|
||||
dep=AIRBASE:FindByName(name)
|
||||
-- Check if the airport has a valid parking spot
|
||||
if self.termtype~=nil and dep~=nil then
|
||||
local _dep=dep --Wrapper.Airbase#AIRBASE
|
||||
local nspots=_dep:GetParkingSpotsNumber(self.termtype)
|
||||
if nspots==0 then
|
||||
dep=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif self:_ZoneExists(name) then
|
||||
if takeoff==RAT.wp.air then
|
||||
@ -3098,7 +3164,8 @@ function RAT:_PickDestination(departure, q, minrange, maxrange, random, landing)
|
||||
if random then
|
||||
|
||||
-- Airports of friendly coalitions.
|
||||
for _,airport in pairs(self.airports) do
|
||||
for _,_airport in pairs(self.airports) do
|
||||
local airport=_airport --Wrapper.Airbase#AIRBASE
|
||||
local name=airport:GetName()
|
||||
if self:_IsFriendly(name) and not self:_Excluded(name) and name~=departure:GetName() then
|
||||
|
||||
@ -3110,7 +3177,14 @@ function RAT:_PickDestination(departure, q, minrange, maxrange, random, landing)
|
||||
if landing==RAT.wp.air then
|
||||
table.insert(destinations, airport:GetZone()) -- insert zone object.
|
||||
else
|
||||
table.insert(destinations, airport) -- insert airport object.
|
||||
-- Check if the requested terminal type is available.
|
||||
local nspot=1
|
||||
if self.termtype then
|
||||
nspot=airport:GetParkingSpotsNumber(self.termtype)
|
||||
end
|
||||
if nspot>0 then
|
||||
table.insert(destinations, airport) -- insert airport object.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -3130,6 +3204,14 @@ function RAT:_PickDestination(departure, q, minrange, maxrange, random, landing)
|
||||
dest=AIRBASE:FindByName(name):GetZone()
|
||||
else
|
||||
dest=AIRBASE:FindByName(name)
|
||||
-- Check if the requested terminal type is available.
|
||||
local nspot=1
|
||||
if self.termtype then
|
||||
nspot=dest:GetParkingSpotsNumber(self.termtype)
|
||||
end
|
||||
if nspot==0 then
|
||||
dest=nil
|
||||
end
|
||||
end
|
||||
elseif self:_ZoneExists(name) then
|
||||
if landing==RAT.wp.air then
|
||||
@ -3287,16 +3369,31 @@ function RAT:_GetAirportsOfMap()
|
||||
end
|
||||
end
|
||||
|
||||
--- Get all "friendly" airports of the current map.
|
||||
--- Get all "friendly" airports of the current map. Fills the self.airports{} table.
|
||||
-- @param #RAT self
|
||||
function RAT:_GetAirportsOfCoalition()
|
||||
for _,coalition in pairs(self.ctable) do
|
||||
for _,airport in pairs(self.airports_map) do
|
||||
for _,_airport in pairs(self.airports_map) do
|
||||
local airport=_airport --Wrapper.Airbase#AIRBASE
|
||||
local category=airport:GetDesc().category
|
||||
if airport:GetCoalition()==coalition then
|
||||
-- Planes cannot land on FARPs.
|
||||
local condition1=self.category==RAT.cat.plane and airport:GetTypeName()=="FARP"
|
||||
--local condition1=self.category==RAT.cat.plane and airport:GetTypeName()=="FARP"
|
||||
local condition1=self.category==RAT.cat.plane and category==Airbase.Category.HELIPAD
|
||||
-- Planes cannot land on ships.
|
||||
local condition2=self.category==RAT.cat.plane and airport:GetCategory()==1
|
||||
--local condition2=self.category==RAT.cat.plane and airport:GetCategory()==1
|
||||
local condition2=self.category==RAT.cat.plane and category==Airbase.Category.SHIP
|
||||
|
||||
-- Check that airport has the requested terminal types.
|
||||
-- NOT good here because we would also not allow any airport zones!
|
||||
--[[
|
||||
local nspots=1
|
||||
if self.termtype then
|
||||
nspots=airport:GetParkingSpotsNumber(self.termtype)
|
||||
end
|
||||
local condition3 = nspots==0
|
||||
]]
|
||||
|
||||
if not (condition1 or condition2) then
|
||||
table.insert(self.airports, airport)
|
||||
end
|
||||
@ -3305,8 +3402,8 @@ function RAT:_GetAirportsOfCoalition()
|
||||
end
|
||||
|
||||
if #self.airports==0 then
|
||||
local text="ERROR! No possible departure/destination airports found."
|
||||
MESSAGE:New(text, 30):ToAll()
|
||||
local text=string.format("No possible departure/destination airports found for RAT %s.", tostring(self.alias))
|
||||
MESSAGE:New(text, 10):ToAll()
|
||||
self:E(RAT.id..text)
|
||||
end
|
||||
end
|
||||
@ -5254,7 +5351,7 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
|
||||
|
||||
if spawnonground then
|
||||
|
||||
-- Shíps and FARPS seem to have a build in queue.
|
||||
-- Sh<EFBFBD>ps and FARPS seem to have a build in queue.
|
||||
if spawnonship or spawnonfarp or spawnonrunway or automatic then
|
||||
self:T(RAT.id..string.format("RAT group %s spawning at farp, ship or runway %s.", self.alias, departure:GetName()))
|
||||
|
||||
|
||||
@ -68,6 +68,8 @@
|
||||
-- @field #number dtBombtrack Time step [sec] used for tracking released bomb/rocket positions. Default 0.005 seconds.
|
||||
-- @field #number BombtrackThreshold Bombs/rockets/missiles are only tracked if player-range distance is smaller than this threashold [m]. Default 25000 m.
|
||||
-- @field #number Tmsg Time [sec] messages to players are displayed. Default 30 sec.
|
||||
-- @field #string examinergroupname Name of the examiner group which should get all messages.
|
||||
-- @field #boolean examinerexclusive If true, only the examiner gets messages. If false, clients and examiner get messages.
|
||||
-- @field #number strafemaxalt Maximum altitude above ground for registering for a strafe run. Default is 914 m = 3000 ft.
|
||||
-- @field #number ndisplayresult Number of (player) results that a displayed. Default is 10.
|
||||
-- @field Utilities.Utils#SMOKECOLOR BombSmokeColor Color id used for smoking bomb targets.
|
||||
@ -234,6 +236,8 @@ RANGE={
|
||||
dtBombtrack=0.005,
|
||||
BombtrackThreshold=25000,
|
||||
Tmsg=30,
|
||||
examinergroupname=nil,
|
||||
examinerexclusive=nil,
|
||||
strafemaxalt=914,
|
||||
ndisplayresult=10,
|
||||
BombSmokeColor=SMOKECOLOR.Red,
|
||||
@ -279,8 +283,8 @@ RANGE.MenuF10={}
|
||||
RANGE.id="RANGE | "
|
||||
|
||||
--- Range script version.
|
||||
-- @field #number version
|
||||
RANGE.version="1.2.0"
|
||||
-- @field #string version
|
||||
RANGE.version="1.2.1"
|
||||
|
||||
--TODO list:
|
||||
--TODO: Add custom weapons, which can be specified by the user.
|
||||
@ -434,6 +438,15 @@ function RANGE:SetMessageTimeDuration(time)
|
||||
self.Tmsg=time or RANGE.Defaults.Tmsg
|
||||
end
|
||||
|
||||
--- Set messages to examiner. The examiner will receive messages from all clients.
|
||||
-- @param #RANGE self
|
||||
-- @param #string examinergroupname Name of the group of the examiner.
|
||||
-- @param #boolean exclusively If true, messages are send exclusively to the examiner, i.e. not to the clients.
|
||||
function RANGE:SetMessageToExaminer(examinergroupname, exclusively)
|
||||
self.examinergroupname=examinergroupname
|
||||
self.examinerexclusive=exclusively
|
||||
end
|
||||
|
||||
--- Set max number of player results that are displayed.
|
||||
-- @param #RANGE self
|
||||
-- @param #number nmax Number of results. Default is 10.
|
||||
@ -2119,7 +2132,7 @@ function RANGE:_DisplayMessageToGroup(_unit, _text, _time, _clear)
|
||||
-- Group ID.
|
||||
local _gid=_unit:GetGroup():GetID()
|
||||
|
||||
if _gid then
|
||||
if _gid and not self.examinerexclusive then
|
||||
if _clear == true then
|
||||
trigger.action.outTextForGroup(_gid, _text, _time, _clear)
|
||||
else
|
||||
@ -2127,6 +2140,17 @@ function RANGE:_DisplayMessageToGroup(_unit, _text, _time, _clear)
|
||||
end
|
||||
end
|
||||
|
||||
if self.examinergroupname~=nil then
|
||||
local _examinerid=GROUP:FindByName(self.examinergroupname):GetID()
|
||||
if _examinerid then
|
||||
if _clear == true then
|
||||
trigger.action.outTextForGroup(_examinerid, _text, _time, _clear)
|
||||
else
|
||||
trigger.action.outTextForGroup(_examinerid, _text, _time)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Toggle status of smoking bomb impact points.
|
||||
|
||||
1129
Moose Development/Moose/Functional/Warehouse.lua
Normal file
1129
Moose Development/Moose/Functional/Warehouse.lua
Normal file
File diff suppressed because it is too large
Load Diff
@ -589,6 +589,12 @@ do -- TASK_CARGO
|
||||
Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
|
||||
Fsm:AddTransition( "Failed", "Fail", "Failed" )
|
||||
|
||||
for _, Group in pairs( SetGroup:GetSet() ) do
|
||||
for __, Unit in pairs( Group:GetUnits() ) do
|
||||
local Unit = Unit -- Wrapper.Unit#UNIT
|
||||
Unit:SetCargoBayWeightLimit()
|
||||
end
|
||||
end
|
||||
|
||||
---- @param #FSM_PROCESS self
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||
@ -610,7 +616,6 @@ do -- TASK_CARGO
|
||||
local TaskUnitName = TaskUnit:GetName()
|
||||
local MenuTime = Task:InitTaskControlMenu( TaskUnit )
|
||||
local MenuControl = Task:GetTaskControlMenu( TaskUnit )
|
||||
local CargoItemCount = TaskUnit:CargoItemCount()
|
||||
|
||||
Task.SetCargo:ForEachCargo(
|
||||
|
||||
@ -635,7 +640,13 @@ do -- TASK_CARGO
|
||||
local TaskGroup = TaskUnit:GetGroup()
|
||||
|
||||
if Cargo:IsUnLoaded() then
|
||||
if CargoItemCount < 1 then
|
||||
local CargoBayFreeWeight = TaskUnit:GetCargoBayFreeWeight()
|
||||
local CargoWeight = Cargo:GetWeight()
|
||||
|
||||
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
|
||||
|
||||
-- Only when there is space within the bay to load the next cargo item!
|
||||
if CargoBayFreeWeight > CargoWeight then
|
||||
if Cargo:IsInReportRadius( TaskUnit:GetPointVec2() ) then
|
||||
local NotInDeployZones = true
|
||||
for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do
|
||||
|
||||
@ -265,14 +265,14 @@ AIRBASE.PersianGulf = {
|
||||
--
|
||||
-- Supported types are:
|
||||
--
|
||||
-- * AIRBASE.TerminalType.Runway: Valid spawn points on runway.
|
||||
-- * AIRBASE.TerminalType.HelicopterOnly: Special spots for Helicopers.
|
||||
-- * AIRBASE.TerminalType.Shelter: Hardened Air Shelter. Currently only on Caucaus map.
|
||||
-- * AIRBASE.TerminalType.OpenMed: Open/Shelter air airplane only.
|
||||
-- * AIRBASE.TerminalType.OpenBig: Open air spawn points. Generally larger but does not guarantee large aircraft are capable of spawning there.
|
||||
-- * AIRBASE.TerminalType.OpenMedOrBig: Combines OpenMed and OpenBig spots.
|
||||
-- * AIRBASE.TerminalType.HelicopterUnsable: Combines HelicopterOnly, OpenMed and OpenBig.
|
||||
-- * AIRBASE.TerminalType.FighterAircraft: Combines Shelter. OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft.
|
||||
-- * AIRBASE.TerminalType.Runway = 16: Valid spawn points on runway.
|
||||
-- * AIRBASE.TerminalType.HelicopterOnly = 40: Special spots for Helicopers.
|
||||
-- * AIRBASE.TerminalType.Shelter = 68: Hardened Air Shelter. Currently only on Caucaus map.
|
||||
-- * AIRBASE.TerminalType.OpenMed = 72: Open/Shelter air airplane only.
|
||||
-- * AIRBASE.TerminalType.OpenBig = 104: Open air spawn points. Generally larger but does not guarantee large aircraft are capable of spawning there.
|
||||
-- * AIRBASE.TerminalType.OpenMedOrBig = 176: Combines OpenMed and OpenBig spots.
|
||||
-- * AIRBASE.TerminalType.HelicopterUnsable = 216: Combines HelicopterOnly, OpenMed and OpenBig.
|
||||
-- * AIRBASE.TerminalType.FighterAircraft = 244: Combines Shelter. OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft.
|
||||
-- @field TerminalType
|
||||
AIRBASE.TerminalType = {
|
||||
Runway=16,
|
||||
@ -349,7 +349,7 @@ function AIRBASE.GetAllAirbases(coalition)
|
||||
|
||||
local airbases={}
|
||||
for _,airbase in pairs(_DATABASE.AIRBASES) do
|
||||
if (coalition~=nil and self:GetCoalition()==coalition) or coalition==nil then
|
||||
if (coalition~=nil and airbase:GetCoalition()==coalition) or coalition==nil then
|
||||
table.insert(airbases, airbase)
|
||||
end
|
||||
end
|
||||
|
||||
@ -121,12 +121,15 @@ GROUPTEMPLATE.Takeoff = {
|
||||
-- @return #GROUP self
|
||||
function GROUP:NewTemplate( GroupTemplate, CoalitionSide, CategoryID, CountryID )
|
||||
local GroupName = GroupTemplate.name
|
||||
|
||||
_DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, CategoryID, CountryID, GroupName )
|
||||
self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) )
|
||||
self:F2( GroupName )
|
||||
|
||||
local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) )
|
||||
self.GroupName = GroupName
|
||||
|
||||
_DATABASE:AddGroup( GroupName )
|
||||
if not _DATABASE.GROUPS[GroupName] then
|
||||
_DATABASE.GROUPS[GroupName] = self
|
||||
end
|
||||
|
||||
self:SetEventPriority( 4 )
|
||||
return self
|
||||
@ -140,7 +143,6 @@ end
|
||||
-- @return #GROUP self
|
||||
function GROUP:Register( GroupName )
|
||||
local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) ) -- #GROUP
|
||||
self:F( GroupName )
|
||||
self.GroupName = GroupName
|
||||
|
||||
self:SetEventPriority( 4 )
|
||||
@ -335,8 +337,7 @@ end
|
||||
|
||||
--- Returns the country of the DCS Group.
|
||||
-- @param #GROUP self
|
||||
-- @return DCS#country.id The country identifier.
|
||||
-- @return #nil The DCS Group is not existing or alive.
|
||||
-- @return DCS#country.id The country identifier or nil if the DCS Group is not existing or alive.
|
||||
function GROUP:GetCountry()
|
||||
self:F2( self.GroupName )
|
||||
|
||||
@ -350,6 +351,40 @@ function GROUP:GetCountry()
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Check if at least one (or all) unit(s) has (have) a certain attribute.
|
||||
-- See [hoggit documentation](https://wiki.hoggitworld.com/view/DCS_func_hasAttribute).
|
||||
-- @param #GROUP self
|
||||
-- @param #string attribute The name of the attribute the group is supposed to have. Valid attributes can be found in the "db_attributes.lua" file which is located at in "C:\Program Files\Eagle Dynamics\DCS World\Scripts\Database".
|
||||
-- @param #boolean all If true, all units of the group must have the attribute in order to return true. Default is only one unit of a heterogenious group needs to have the attribute.
|
||||
-- @return #boolean Group has this attribute.
|
||||
function GROUP:HasAttribute(attribute, all)
|
||||
|
||||
-- Get all units of the group.
|
||||
local _units=self:GetUnits()
|
||||
|
||||
local _allhave=true
|
||||
local _onehas=false
|
||||
|
||||
for _,_unit in pairs(_units) do
|
||||
local _unit=_unit --Wrapper.Unit#UNIT
|
||||
if _unit then
|
||||
local _hastit=_unit:HasAttribute(attribute)
|
||||
if _hastit==true then
|
||||
_onehas=true
|
||||
else
|
||||
_allhave=false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if all==true then
|
||||
return _allhave
|
||||
else
|
||||
return _onehas
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns the maximum speed of the group.
|
||||
-- If the group is heterogenious and consists of different units, the max speed of the slowest unit is returned.
|
||||
-- @param #GROUP self
|
||||
@ -1339,15 +1374,34 @@ function GROUP:Respawn( Template, Reset )
|
||||
end
|
||||
|
||||
|
||||
--- @param Wrapper.Group#GROUP self
|
||||
function GROUP:RespawnAtAirbase( AirbaseRespawn, Takeoff, TakeoffAltitude ) -- R2.4
|
||||
self:F( { AirbaseRespawn, Takeoff, TakeoffAltitude } )
|
||||
--- Respawn a group at an airbase.
|
||||
-- Note that the group has to be on parking spots at the airbase already in order for this to work.
|
||||
-- So each unit of the group is respawned at exactly the same parking spot as it currently occupies.
|
||||
-- @param Wrapper.Group#GROUP self
|
||||
-- @param #table SpawnTemplate (Optional) The spawn template for the group. If no template is given it is exacted from the group.
|
||||
-- @param Core.Spawn#SPAWN.Takeoff Takeoff (Optional) Takeoff type. Sould be either SPAWN.Takeoff.Cold or SPAWN.Takeoff.Hot. Default is SPAWN.Takeoff.Hot.
|
||||
-- @param #boolean Uncontrolled (Optional) If true, spawn in uncontrolled state.
|
||||
-- @return Wrapper.Group#GROUP Group spawned at airbase or nil if group could not be spawned.
|
||||
function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) -- R2.4
|
||||
self:F2( { SpawnTemplate, Takeoff, Uncontrolled} )
|
||||
|
||||
local PointVec3 = AirbaseRespawn:GetPointVec3()
|
||||
-- Get closest airbase. Should be the one we are currently on.
|
||||
local airbase=self:GetCoordinate():GetClosestAirbase()
|
||||
|
||||
if airbase then
|
||||
self:F2("Closest airbase = "..airbase:GetName())
|
||||
else
|
||||
self:E("ERROR: could not find closest airbase!")
|
||||
return nil
|
||||
end
|
||||
-- Takeoff type. Default hot.
|
||||
Takeoff = Takeoff or SPAWN.Takeoff.Hot
|
||||
|
||||
local SpawnTemplate = self:GetTemplate()
|
||||
-- Coordinate of the airbase.
|
||||
local AirbaseCoord=airbase:GetCoordinate()
|
||||
|
||||
-- Spawn template.
|
||||
SpawnTemplate = SpawnTemplate or self:GetTemplate()
|
||||
|
||||
if SpawnTemplate then
|
||||
|
||||
@ -1358,78 +1412,62 @@ function GROUP:RespawnAtAirbase( AirbaseRespawn, Takeoff, TakeoffAltitude ) -- R
|
||||
SpawnPoint.helipadId = nil
|
||||
SpawnPoint.airdromeId = nil
|
||||
|
||||
local AirbaseID = AirbaseRespawn:GetID()
|
||||
local AirbaseCategory = AirbaseRespawn:GetDesc().category
|
||||
self:F( { AirbaseCategory = AirbaseCategory, Ship = Airbase.Category.SHIP, Helipad = Airbase.Category.HELIPAD, Airdrome = Airbase.Category.AIRDROME } )
|
||||
-- Aibase id and category.
|
||||
local AirbaseID = airbase:GetID()
|
||||
local AirbaseCategory = airbase:GetDesc().category
|
||||
|
||||
if AirbaseCategory == Airbase.Category.SHIP then
|
||||
SpawnPoint.linkUnit = AirbaseID
|
||||
SpawnPoint.helipadId = AirbaseID
|
||||
elseif AirbaseCategory == Airbase.Category.HELIPAD then
|
||||
SpawnPoint.linkUnit = AirbaseID
|
||||
if AirbaseCategory == Airbase.Category.SHIP or AirbaseCategory == Airbase.Category.HELIPAD then
|
||||
SpawnPoint.linkUnit = AirbaseID
|
||||
SpawnPoint.helipadId = AirbaseID
|
||||
elseif AirbaseCategory == Airbase.Category.AIRDROME then
|
||||
SpawnPoint.airdromeId = AirbaseID
|
||||
end
|
||||
|
||||
SpawnPoint.alt = 0
|
||||
|
||||
SpawnPoint.type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type
|
||||
SpawnPoint.alt = AirbaseCoord:GetLandHeight()
|
||||
SpawnPoint.type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type
|
||||
SpawnPoint.action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action
|
||||
|
||||
-- Get the units of the group.
|
||||
local units=self:GetUnits()
|
||||
|
||||
-- Translate the position of the Group Template to the Vec3.
|
||||
for UnitID = 1, #SpawnTemplate.units do
|
||||
self:T( 'Before Translation SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y )
|
||||
for UnitID,_unit in pairs(units) do
|
||||
|
||||
-- These cause a lot of confusion.
|
||||
local UnitTemplate = SpawnTemplate.units[UnitID]
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
UnitTemplate.parking = 15
|
||||
UnitTemplate.parking_id = "30"
|
||||
UnitTemplate.alt = 0
|
||||
-- Get closest parking spot of current unit. Note that we look for occupied spots since the unit is currently sitting on it!
|
||||
local Parkingspot, TermialID, Distance=unit:GetCoordinate():GetClosestParkingSpot(airbase)
|
||||
|
||||
local SX = UnitTemplate.x
|
||||
local SY = UnitTemplate.y
|
||||
local BX = SpawnPoint.x
|
||||
local BY = SpawnPoint.y
|
||||
local TX = PointVec3.x + ( SX - BX )
|
||||
local TY = PointVec3.z + ( SY - BY )
|
||||
--Parkingspot:MarkToAll("parking spot")
|
||||
self:T2(string.format("Closest parking spot distance = %s, terminal ID=%s", tostring(Distance), tostring(TermialID)))
|
||||
|
||||
UnitTemplate.x = TX
|
||||
UnitTemplate.y = TY
|
||||
-- Get unit coordinates for respawning position.
|
||||
local uc=unit:GetCoordinate()
|
||||
SpawnTemplate.units[UnitID].x = Parkingspot.x
|
||||
SpawnTemplate.units[UnitID].y = Parkingspot.z
|
||||
SpawnTemplate.units[UnitID].alt = Parkingspot.y
|
||||
|
||||
SpawnTemplate.units[UnitID].parking = TermialID
|
||||
SpawnTemplate.units[UnitID].parking_id = nil
|
||||
|
||||
if Takeoff == GROUP.Takeoff.Air then
|
||||
UnitTemplate.alt = PointVec3.y + ( TakeoffAltitude or 200 )
|
||||
--else
|
||||
-- UnitTemplate.alt = PointVec3.y + 10
|
||||
end
|
||||
self:T( 'After Translation SpawnTemplate.units['..UnitID..'].x = ' .. UnitTemplate.x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. UnitTemplate.y )
|
||||
end
|
||||
|
||||
SpawnPoint.x = PointVec3.x
|
||||
SpawnPoint.y = PointVec3.z
|
||||
SpawnPoint.x = AirbaseCoord.x
|
||||
SpawnPoint.y = AirbaseCoord.z
|
||||
|
||||
if Takeoff == GROUP.Takeoff.Air then
|
||||
SpawnPoint.alt = PointVec3.y + ( TakeoffAltitude or 200 )
|
||||
--else
|
||||
-- SpawnPoint.alt = PointVec3.y + 10
|
||||
end
|
||||
SpawnTemplate.x = AirbaseCoord.x
|
||||
SpawnTemplate.y = AirbaseCoord.z
|
||||
|
||||
SpawnTemplate.x = PointVec3.x
|
||||
SpawnTemplate.y = PointVec3.z
|
||||
-- Set uncontrolled state.
|
||||
SpawnTemplate.uncontrolled=Uncontrolled
|
||||
|
||||
local GroupSpawned = self:Respawn( SpawnTemplate )
|
||||
-- Destroy and respawn.
|
||||
self:Destroy()
|
||||
_DATABASE:Spawn( SpawnTemplate )
|
||||
|
||||
-- When spawned in the air, we need to generate a Takeoff Event
|
||||
-- Reset events.
|
||||
self:ResetEvents()
|
||||
|
||||
if Takeoff == GROUP.Takeoff.Air then
|
||||
for UnitID, UnitSpawned in pairs( GroupSpawned:GetUnits() ) do
|
||||
SCHEDULER:New( nil, BASE.CreateEventTakeoff, { GroupSpawned, timer.getTime(), UnitSpawned:GetDCSObject() } , 1 )
|
||||
end
|
||||
end
|
||||
|
||||
return GroupSpawned
|
||||
return self
|
||||
end
|
||||
|
||||
return nil
|
||||
|
||||
@ -216,7 +216,7 @@ end
|
||||
function IDENTIFIABLE:GetDesc()
|
||||
self:F2( self.IdentifiableName )
|
||||
|
||||
local DCSIdentifiable = self:GetDCSObject()
|
||||
local DCSIdentifiable = self:GetDCSObject() -- DCS#Object
|
||||
|
||||
if DCSIdentifiable then
|
||||
local IdentifiableDesc = DCSIdentifiable:getDesc()
|
||||
|
||||
@ -243,7 +243,7 @@ end
|
||||
|
||||
--- Get the bounding box of the underlying POSITIONABLE DCS Object.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return DCS#Distance The bounding box of the POSITIONABLE.
|
||||
-- @return DCS#Box3 The bounding box of the POSITIONABLE.
|
||||
-- @return #nil The POSITIONABLE is not existing or alive.
|
||||
function POSITIONABLE:GetBoundingBox() --R2.1
|
||||
self:F2()
|
||||
@ -264,6 +264,29 @@ function POSITIONABLE:GetBoundingBox() --R2.1
|
||||
end
|
||||
|
||||
|
||||
--- Get the bounding radius of the underlying POSITIONABLE DCS Object.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return DCS#Distance The bounding radius of the POSITIONABLE.
|
||||
-- @return #nil The POSITIONABLE is not existing or alive.
|
||||
function POSITIONABLE:GetBoundingRadius()
|
||||
self:F2()
|
||||
|
||||
local Box = self:GetBoundingBox()
|
||||
|
||||
|
||||
if Box then
|
||||
local X = Box.max.x - Box.min.x
|
||||
local Z = Box.max.z - Box.min.z
|
||||
local CX = X / 2
|
||||
local CZ = Z / 2
|
||||
return math.max( CX, CZ )
|
||||
end
|
||||
|
||||
BASE:E( { "Cannot GetBoundingRadius", Positionable = self, Alive = self:IsAlive() } )
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns the altitude of the POSITIONABLE.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @return DCS#Distance The altitude of the POSITIONABLE.
|
||||
@ -323,7 +346,7 @@ end
|
||||
|
||||
--- Returns the POSITIONABLE heading in degrees.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @return #number The POSTIONABLE heading
|
||||
-- @return #number The POSITIONABLE heading
|
||||
-- @return #nil The POSITIONABLE is not existing or alive.
|
||||
function POSITIONABLE:GetHeading()
|
||||
local DCSPositionable = self:GetDCSObject()
|
||||
@ -347,6 +370,52 @@ function POSITIONABLE:GetHeading()
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Is Methods
|
||||
|
||||
--- Returns if the unit is of an air category.
|
||||
-- If the unit is a helicopter or a plane, then this method will return true, otherwise false.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return #boolean Air category evaluation result.
|
||||
function POSITIONABLE:IsAir()
|
||||
self:F2()
|
||||
|
||||
local DCSUnit = self:GetDCSObject()
|
||||
|
||||
if DCSUnit then
|
||||
local UnitDescriptor = DCSUnit:getDesc()
|
||||
self:T3( { UnitDescriptor.category, Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
|
||||
|
||||
local IsAirResult = ( UnitDescriptor.category == Unit.Category.AIRPLANE ) or ( UnitDescriptor.category == Unit.Category.HELICOPTER )
|
||||
|
||||
self:T3( IsAirResult )
|
||||
return IsAirResult
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns if the unit is of an ground category.
|
||||
-- If the unit is a ground vehicle or infantry, this method will return true, otherwise false.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return #boolean Ground category evaluation result.
|
||||
function POSITIONABLE:IsGround()
|
||||
self:F2()
|
||||
|
||||
local DCSUnit = self:GetDCSObject()
|
||||
|
||||
if DCSUnit then
|
||||
local UnitDescriptor = DCSUnit:getDesc()
|
||||
self:T3( { UnitDescriptor.category, Unit.Category.GROUND_UNIT } )
|
||||
|
||||
local IsGroundResult = ( UnitDescriptor.category == Unit.Category.GROUND_UNIT )
|
||||
|
||||
self:T3( IsGroundResult )
|
||||
return IsGroundResult
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Returns true if the POSITIONABLE is in the air.
|
||||
-- Polymorphic, is overridden in GROUP and UNIT.
|
||||
@ -798,56 +867,148 @@ function POSITIONABLE:GetLaserCode() --R2.1
|
||||
return self.LaserCode
|
||||
end
|
||||
|
||||
--- Add cargo.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @param Core.Cargo#CARGO Cargo
|
||||
-- @return #POSITIONABLE
|
||||
function POSITIONABLE:AddCargo( Cargo )
|
||||
self.__.Cargo[Cargo] = Cargo
|
||||
return self
|
||||
end
|
||||
do -- Cargo
|
||||
|
||||
--- Get all contained cargo.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return #POSITIONABLE
|
||||
function POSITIONABLE:GetCargo()
|
||||
return self.__.Cargo
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Remove cargo.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @param Core.Cargo#CARGO Cargo
|
||||
-- @return #POSITIONABLE
|
||||
function POSITIONABLE:RemoveCargo( Cargo )
|
||||
self.__.Cargo[Cargo] = nil
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns if carrier has given cargo.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return Core.Cargo#CARGO Cargo
|
||||
function POSITIONABLE:HasCargo( Cargo )
|
||||
return self.__.Cargo[Cargo]
|
||||
end
|
||||
|
||||
--- Clear all cargo.
|
||||
-- @param #POSITIONABLE self
|
||||
function POSITIONABLE:ClearCargo()
|
||||
self.__.Cargo = {}
|
||||
end
|
||||
|
||||
--- Get cargo item count.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return Core.Cargo#CARGO Cargo
|
||||
function POSITIONABLE:CargoItemCount()
|
||||
local ItemCount = 0
|
||||
for CargoName, Cargo in pairs( self.__.Cargo ) do
|
||||
ItemCount = ItemCount + Cargo:GetCount()
|
||||
--- Add cargo.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @param Core.Cargo#CARGO Cargo
|
||||
-- @return #POSITIONABLE
|
||||
function POSITIONABLE:AddCargo( Cargo )
|
||||
self.__.Cargo[Cargo] = Cargo
|
||||
return self
|
||||
end
|
||||
return ItemCount
|
||||
end
|
||||
|
||||
--- Get all contained cargo.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return #POSITIONABLE
|
||||
function POSITIONABLE:GetCargo()
|
||||
return self.__.Cargo
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Remove cargo.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @param Core.Cargo#CARGO Cargo
|
||||
-- @return #POSITIONABLE
|
||||
function POSITIONABLE:RemoveCargo( Cargo )
|
||||
self.__.Cargo[Cargo] = nil
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns if carrier has given cargo.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return Core.Cargo#CARGO Cargo
|
||||
function POSITIONABLE:HasCargo( Cargo )
|
||||
return self.__.Cargo[Cargo]
|
||||
end
|
||||
|
||||
--- Clear all cargo.
|
||||
-- @param #POSITIONABLE self
|
||||
function POSITIONABLE:ClearCargo()
|
||||
self.__.Cargo = {}
|
||||
end
|
||||
|
||||
--- Is cargo bay empty.
|
||||
-- @param #POSITIONABLE self
|
||||
function POSITIONABLE:IsCargoEmpty()
|
||||
local IsEmpty = true
|
||||
for _, Cargo in pairs( self.__.Cargo ) do
|
||||
IsEmpty = false
|
||||
break
|
||||
end
|
||||
return IsEmpty
|
||||
end
|
||||
|
||||
--- Get cargo item count.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return Core.Cargo#CARGO Cargo
|
||||
function POSITIONABLE:CargoItemCount()
|
||||
local ItemCount = 0
|
||||
for CargoName, Cargo in pairs( self.__.Cargo ) do
|
||||
ItemCount = ItemCount + Cargo:GetCount()
|
||||
end
|
||||
return ItemCount
|
||||
end
|
||||
|
||||
-- --- Get Cargo Bay Free Volume in m3.
|
||||
-- -- @param #POSITIONABLE self
|
||||
-- -- @return #number CargoBayFreeVolume
|
||||
-- function POSITIONABLE:GetCargoBayFreeVolume()
|
||||
-- local CargoVolume = 0
|
||||
-- for CargoName, Cargo in pairs( self.__.Cargo ) do
|
||||
-- CargoVolume = CargoVolume + Cargo:GetVolume()
|
||||
-- end
|
||||
-- return self.__.CargoBayVolumeLimit - CargoVolume
|
||||
-- end
|
||||
--
|
||||
--- Get Cargo Bay Free Weight in kg.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return #number CargoBayFreeWeight
|
||||
function POSITIONABLE:GetCargoBayFreeWeight()
|
||||
local CargoWeight = 0
|
||||
for CargoName, Cargo in pairs( self.__.Cargo ) do
|
||||
CargoWeight = CargoWeight + Cargo:GetWeight()
|
||||
end
|
||||
return self.__.CargoBayWeightLimit - CargoWeight
|
||||
end
|
||||
|
||||
-- --- Get Cargo Bay Volume Limit in m3.
|
||||
-- -- @param #POSITIONABLE self
|
||||
-- -- @param #number VolumeLimit
|
||||
-- function POSITIONABLE:SetCargoBayVolumeLimit( VolumeLimit )
|
||||
-- self.__.CargoBayVolumeLimit = VolumeLimit
|
||||
-- end
|
||||
|
||||
--- Get Cargo Bay Weight Limit in kg.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @param #number WeightLimit
|
||||
function POSITIONABLE:SetCargoBayWeightLimit( WeightLimit )
|
||||
if WeightLimit then
|
||||
self.__.CargoBayWeightLimit = WeightLimit
|
||||
else
|
||||
-- If weightlimit is not provided, we will calculate it depending on the type of unit.
|
||||
|
||||
-- When an airplane or helicopter, we calculate the weightlimit based on the descriptor.
|
||||
if self:IsAir() then
|
||||
local Desc = self:GetDesc()
|
||||
self:F({Desc=Desc})
|
||||
self.__.CargoBayWeightLimit = Desc.massMax - ( Desc.massEmpty + Desc.fuelMassMax )
|
||||
else
|
||||
local Desc = self:GetDesc()
|
||||
|
||||
local Weights = {
|
||||
["M1126 Stryker ICV"] = 9,
|
||||
["M-113"] = 9,
|
||||
["AAV7"] = 25,
|
||||
["M2A1_halftrack"] = 9,
|
||||
["BMD-1"] = 9,
|
||||
["BMP-1"] = 8,
|
||||
["BMP-2"] = 7,
|
||||
["BMP-3"] = 8,
|
||||
["Boman"] = 25,
|
||||
["BTR-80"] = 9,
|
||||
["BTR_D"] = 12,
|
||||
["Cobra"] = 8,
|
||||
["LAV-25"] = 6,
|
||||
["M-2 Bradley"] = 6,
|
||||
["M1043 HMMWV Armament"] = 4,
|
||||
["M1045 HMMWV TOW"] = 4,
|
||||
["M1126 Stryker ICV"] = 9,
|
||||
["M1134 Stryker ATGM"] = 9,
|
||||
["Marder"] = 6,
|
||||
["MCV-80"] = 9,
|
||||
["MLRS FDDM"] = 4,
|
||||
["MTLB"] = 25,
|
||||
["TPZ"] = 10,
|
||||
}
|
||||
|
||||
local CargoBayWeightLimit = ( Weights[Desc.typeName] or 0 ) * 70
|
||||
self.__.CargoBayWeightLimit = CargoBayWeightLimit
|
||||
end
|
||||
end
|
||||
end
|
||||
end --- Cargo
|
||||
|
||||
--- Signal a flare at the position of the POSITIONABLE.
|
||||
-- @param #POSITIONABLE self
|
||||
|
||||
@ -854,51 +854,7 @@ end
|
||||
|
||||
|
||||
|
||||
-- Is methods
|
||||
|
||||
--- Returns if the unit is of an air category.
|
||||
-- If the unit is a helicopter or a plane, then this method will return true, otherwise false.
|
||||
-- @param #UNIT self
|
||||
-- @return #boolean Air category evaluation result.
|
||||
function UNIT:IsAir()
|
||||
self:F2()
|
||||
|
||||
local DCSUnit = self:GetDCSObject()
|
||||
|
||||
if DCSUnit then
|
||||
local UnitDescriptor = DCSUnit:getDesc()
|
||||
self:T3( { UnitDescriptor.category, Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
|
||||
|
||||
local IsAirResult = ( UnitDescriptor.category == Unit.Category.AIRPLANE ) or ( UnitDescriptor.category == Unit.Category.HELICOPTER )
|
||||
|
||||
self:T3( IsAirResult )
|
||||
return IsAirResult
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns if the unit is of an ground category.
|
||||
-- If the unit is a ground vehicle or infantry, this method will return true, otherwise false.
|
||||
-- @param #UNIT self
|
||||
-- @return #boolean Ground category evaluation result.
|
||||
function UNIT:IsGround()
|
||||
self:F2()
|
||||
|
||||
local DCSUnit = self:GetDCSObject()
|
||||
|
||||
if DCSUnit then
|
||||
local UnitDescriptor = DCSUnit:getDesc()
|
||||
self:T3( { UnitDescriptor.category, Unit.Category.GROUND_UNIT } )
|
||||
|
||||
local IsGroundResult = ( UnitDescriptor.category == Unit.Category.GROUND_UNIT )
|
||||
|
||||
self:T3( IsGroundResult )
|
||||
return IsGroundResult
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns if the unit is a friendly unit.
|
||||
-- @param #UNIT self
|
||||
|
||||
@ -57,6 +57,7 @@ Functional/ZoneCaptureCoalition.lua
|
||||
Functional/Artillery.lua
|
||||
Functional/Suppression.lua
|
||||
Functional/PseudoATC.lua
|
||||
Functional/Warehouse.lua
|
||||
|
||||
AI/AI_Balancer.lua
|
||||
AI/AI_A2A.lua
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user