Added new routines by Sven.
Due to conflicts just overwriting the old ones.
This commit is contained in:
funkyfranky 2018-09-06 23:25:19 +02:00
parent 3f875ce276
commit c2064690f1
8 changed files with 1273 additions and 1148 deletions

View File

@ -0,0 +1,435 @@
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry and other cargo.
--
-- ===
--
-- ### Author: **FlightControl**
--
-- ===
--
-- @module AI.AI_Cargo
-- @image Cargo.JPG
--- @type AI_CARGO
-- @extends Core.Fsm#FSM_CONTROLLABLE
--- Base class for the dynamic cargo handling capability for AI groups.
--
-- Carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- The AI_CARGO module uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
-- CARGO derived objects must be declared within the mission to make the AI_CARGO object recognize the cargo.
-- Please consult the @{Cargo.Cargo} module for more information.
--
-- The derived classes from this module are:
--
-- * @{AI.AI_Cargo_APC} - Cargo transportation using APCs and other vehicles between zones.
-- * @{AI.AI_Cargo_Helicopter} - Cargo transportation using helicopters between zones.
-- * @{AI.AI_Cargo_Airplane} - Cargo transportation using airplanes to and from airbases.
--
-- @field #AI_CARGO
AI_CARGO = {
ClassName = "AI_CARGO",
Coordinate = nil, -- Core.Point#COORDINATE,
Carrier_Cargo = {},
}
--- Creates a new AI_CARGO object.
-- @param #AI_CARGO self
-- @param Wrapper.Group#GROUP Carrier
-- @param Core.Set#SET_CARGO CargoSet
-- @param #number CombatRadius
-- @return #AI_CARGO
function AI_CARGO:New( Carrier, CargoSet )
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New( Carrier ) ) -- #AI_CARGO
self.CargoSet = CargoSet -- Core.Set#SET_CARGO
self.CargoCarrier = Carrier -- Wrapper.Group#GROUP
self:SetStartState( "Unloaded" )
self:AddTransition( "Unloaded", "Pickup", "*" )
self:AddTransition( "Loaded", "Deploy", "*" )
self:AddTransition( "*", "Load", "Boarding" )
self:AddTransition( { "Boarding", "Loaded" }, "Board", "Boarding" )
self:AddTransition( "Boarding", "Loaded", "Boarding" )
self:AddTransition( "Boarding", "PickedUp", "Loaded" )
self:AddTransition( "Loaded", "Unload", "Unboarding" )
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
self:AddTransition( "Unboarding", "Unloaded", "Unboarding" )
self:AddTransition( "Unboarding", "Deployed", "Unloaded" )
--- Pickup Handler OnBefore for AI_CARGO
-- @function [parent=#AI_CARGO] OnBeforePickup
-- @param #AI_CARGO self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
-- @return #boolean
--- Pickup Handler OnAfter for AI_CARGO
-- @function [parent=#AI_CARGO] OnAfterPickup
-- @param #AI_CARGO self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
--- Pickup Trigger for AI_CARGO
-- @function [parent=#AI_CARGO] Pickup
-- @param #AI_CARGO self
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
--- Pickup Asynchronous Trigger for AI_CARGO
-- @function [parent=#AI_CARGO] __Pickup
-- @param #AI_CARGO self
-- @param #number Delay
-- @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
-- @function [parent=#AI_CARGO] OnBeforeDeploy
-- @param #AI_CARGO self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
-- @return #boolean
--- Deploy Handler OnAfter for AI_CARGO
-- @function [parent=#AI_CARGO] OnAfterDeploy
-- @param #AI_CARGO self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
--- Deploy Trigger for AI_CARGO
-- @function [parent=#AI_CARGO] Deploy
-- @param #AI_CARGO self
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
--- Deploy Asynchronous Trigger for AI_CARGO
-- @function [parent=#AI_CARGO] __Deploy
-- @param #AI_CARGO self
-- @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.
--- Loaded Handler OnAfter for AI_CARGO
-- @function [parent=#AI_CARGO] OnAfterLoaded
-- @param #AI_CARGO self
-- @param Wrapper.Group#GROUP Carrier
-- @param #string From
-- @param #string Event
-- @param #string To
--- Unloaded Handler OnAfter for AI_CARGO
-- @function [parent=#AI_CARGO] OnAfterUnloaded
-- @param #AI_CARGO self
-- @param Wrapper.Group#GROUP Carrier
-- @param #string From
-- @param #string Event
-- @param #string To
for _, CarrierUnit in pairs( Carrier:GetUnits() ) do
CarrierUnit:SetCargoBayWeightLimit()
end
self.Transporting = false
self.Relocating = false
return self
end
function AI_CARGO:IsTransporting()
return self.Transporting == true
end
function AI_CARGO:IsRelocating()
return self.Relocating == true
end
--- On before Load event.
-- @param #AI_CARGO self
-- @param Wrapper.Group#GROUP Carrier
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
function AI_CARGO:onbeforeLoad( Carrier, From, Event, To, PickupZone )
self:F( { Carrier, From, Event, To } )
local Boarding = false
local LoadInterval = 10
local LoadDelay = 10
local Carrier_List = {}
local Carrier_Weight = {}
if Carrier and Carrier:IsAlive() then
self.Carrier_Cargo = {}
for _, CarrierUnit in pairs( Carrier:GetUnits() ) do
local CarrierUnit = CarrierUnit -- Wrapper.Unit#UNIT
local CargoBayFreeWeight = CarrierUnit:GetCargoBayFreeWeight()
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
Carrier_List[#Carrier_List+1] = CarrierUnit
Carrier_Weight[CarrierUnit] = CargoBayFreeWeight
end
local Carrier_Count = #Carrier_List
local Carrier_Index = 1
for _, Cargo in UTILS.spairs( self.CargoSet:GetSet(), function( t, a, b ) return t[a]:GetWeight() > t[b]:GetWeight() end ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
self:F( { IsUnLoaded = Cargo:IsUnLoaded(), IsDeployed = Cargo:IsDeployed(), Cargo:GetName(), Carrier:GetName() } )
local Loaded = false
-- Try all Carriers, but start from the one according the Carrier_Index
for Carrier_Loop = 1, #Carrier_List do
local CarrierUnit = Carrier_List[Carrier_Index] -- Wrapper.Unit#UNIT
-- This counters loop through the available Carriers.
Carrier_Index = Carrier_Index + 1
if Carrier_Index > Carrier_Count then
Carrier_Index = 1
end
if Cargo:IsUnLoaded() then -- and not Cargo:IsDeployed() then
if Cargo:IsInLoadRadius( CarrierUnit:GetCoordinate() ) then
self:F( { "In radius", CarrierUnit:GetName() } )
local CargoWeight = Cargo:GetWeight()
-- Only when there is space within the bay to load the next cargo item!
if Carrier_Weight[CarrierUnit] > CargoWeight then --and CargoBayFreeVolume > CargoVolume then
Carrier:RouteStop()
--Cargo:Ungroup()
Cargo:__Board( LoadDelay, CarrierUnit, 25 )
LoadDelay = LoadDelay + LoadInterval
self:__Board( LoadDelay, Cargo, CarrierUnit, PickupZone )
-- So now this CarrierUnit has Cargo that is being loaded.
-- This will be used further in the logic to follow and to check cargo status.
self.Carrier_Cargo[Cargo] = CarrierUnit
Boarding = true
Carrier_Weight[CarrierUnit] = Carrier_Weight[CarrierUnit] - CargoWeight
Loaded = true
-- Ok, we loaded a cargo, now we can stop the loop.
break
end
end
end
end
if not Loaded then
-- If the cargo wasn't loaded in one of the carriers, then we need to stop the loading.
end
end
end
return Boarding
end
--- On after Board event.
-- @param #AI_CARGO self
-- @param Wrapper.Group#GROUP Carrier
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Cargo.Cargo#CARGO Cargo Cargo object.
-- @param Wrapper.Unit#UNIT CarrierUnit
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
function AI_CARGO:onafterBoard( Carrier, From, Event, To, Cargo, CarrierUnit, PickupZone )
self:F( { Carrier, From, Event, To, Cargo, CarrierUnit:GetName() } )
if Carrier and Carrier:IsAlive() then
self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), Carrier:GetName() } )
if not Cargo:IsLoaded() then
self:__Board( 10, Cargo, CarrierUnit, PickupZone )
return
end
end
self:__Loaded( 10, Cargo, CarrierUnit, PickupZone )
end
--- On after Loaded event.
-- @param #AI_CARGO self
-- @param Wrapper.Group#GROUP Carrier
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @return #boolean Cargo loaded.
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
function AI_CARGO:onafterLoaded( Carrier, From, Event, To, Cargo, PickupZone )
self:F( { Carrier, From, Event, To } )
local Loaded = true
if Carrier and Carrier:IsAlive() then
for Cargo, CarrierUnit in pairs( self.Carrier_Cargo ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
self:F( { IsLoaded = Cargo:IsLoaded(), IsDestroyed = Cargo:IsDestroyed(), Cargo:GetName(), Carrier:GetName() } )
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
Loaded = false
end
end
end
if Loaded then
self:PickedUp( PickupZone )
end
end
--- On after PickedUp event.
-- @param #AI_CARGO self
-- @param Wrapper.Group#GROUP Carrier
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
function AI_CARGO:onafterPickedUp( Carrier, From, Event, To, PickupZone )
self:F( { Carrier, From, Event, To } )
Carrier:RouteResume()
end
--- On after Unload event.
-- @param #AI_CARGO self
-- @param Wrapper.Group#GROUP Carrier
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
function AI_CARGO:onafterUnload( Carrier, From, Event, To, DeployZone )
self:F( { Carrier, From, Event, To, DeployZone } )
local UnboardInterval = 10
local UnboardDelay = 10
if Carrier and Carrier:IsAlive() then
for _, CarrierUnit in pairs( Carrier:GetUnits() ) do
local CarrierUnit = CarrierUnit -- Wrapper.Unit#UNIT
Carrier:RouteStop()
for _, Cargo in pairs( CarrierUnit:GetCargo() ) do
if Cargo:IsLoaded() then
Cargo:__UnBoard( UnboardDelay )
UnboardDelay = UnboardDelay + UnboardInterval
Cargo:SetDeployed( true )
self:__Unboard( UnboardDelay, Cargo, CarrierUnit, DeployZone )
end
end
end
end
end
--- On after Unboard event.
-- @param #AI_CARGO self
-- @param Wrapper.Group#GROUP Carrier
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #string Cargo.Cargo#CARGO Cargo Cargo object.
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
function AI_CARGO:onafterUnboard( Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone )
self:F( { Carrier, From, Event, To, Cargo:GetName() } )
if Carrier and Carrier:IsAlive() then
if not Cargo:IsUnLoaded() then
self:__Unboard( 10, Cargo, CarrierUnit, DeployZone )
return
end
end
self:Unloaded( Cargo, CarrierUnit, DeployZone )
end
--- On after Unloaded event.
-- @param #AI_CARGO self
-- @param Wrapper.Group#GROUP Carrier
-- @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.
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
function AI_CARGO:onafterUnloaded( Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone )
self:F( { Carrier, From, Event, To, Cargo:GetName(), DeployZone = DeployZone } )
local AllUnloaded = true
--Cargo:Regroup()
if Carrier and Carrier:IsAlive() then
for _, CarrierUnit in pairs( Carrier:GetUnits() ) do
local CarrierUnit = CarrierUnit -- Wrapper.Unit#UNIT
local IsEmpty = CarrierUnit:IsCargoEmpty()
self:I({ IsEmpty = IsEmpty })
if not IsEmpty then
AllUnloaded = false
break
end
end
if AllUnloaded == true then
if DeployZone == true then
self.Carrier_Cargo = {}
end
self.CargoCarrier = Carrier
end
end
if AllUnloaded == true then
self:__Deployed( 5, DeployZone )
end
end
--- On after Deployed event.
-- @param #AI_CARGO self
-- @param Wrapper.Group#GROUP Carrier
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
function AI_CARGO:onafterDeployed( Carrier, From, Event, To, DeployZone )
self:F( { Carrier, From, Event, To, DeployZone = DeployZone } )
self:__Guard( 0.1 )
end

View File

@ -1,4 +1,4 @@
--- **AI** -- (R2.3) - Models the intelligent transportation of infantry and other cargo.
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry and other cargo.
--
-- ===
--
@ -10,15 +10,16 @@
-- @image AI_Cargo_Dispatching_For_APC.JPG
--- @type AI_CARGO_APC
-- @extends Core.Fsm#FSM_CONTROLLABLE
-- @extends AI.AI_Cargo#AI_CARGO
--- Brings a dynamic cargo handling capability for AI groups.
--- Brings a dynamic cargo handling capability for an AI vehicle group.
--
-- Armoured Personnel Carriers (APC), Trucks, Jeeps and other ground based carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- The AI\_CARGO\APC module uses the @{Cargo} capabilities within the MOOSE framework.
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\APC object recognize the cargo.
-- Please consult the @{Cargo} module for more information.
--
-- The AI_CARGO_APC class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
-- @{Cargo.Cargo} must be declared within the mission to make the AI_CARGO_APC object recognize the cargo.
-- Please consult the @{Cargo.Cargo} module for more information.
--
-- ## Cargo loading.
--
@ -74,7 +75,6 @@
AI_CARGO_APC = {
ClassName = "AI_CARGO_APC",
Coordinate = nil, -- Core.Point#COORDINATE,
APC_Cargo = {},
}
--- Creates a new AI_CARGO_APC object.
@ -85,125 +85,21 @@ AI_CARGO_APC = {
-- @return #AI_CARGO_APC
function AI_CARGO_APC:New( APC, CargoSet, CombatRadius )
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_CARGO_APC
local self = BASE:Inherit( self, AI_CARGO:New( APC, CargoSet ) ) -- #AI_CARGO_APC
self.CargoSet = CargoSet -- Core.Set#SET_CARGO
self.CombatRadius = CombatRadius
self:SetStartState( "Unloaded" )
self:AddTransition( "Unloaded", "Pickup", "*" )
self:AddTransition( "Loaded", "Deploy", "*" )
self:AddTransition( "*", "Load", "Boarding" )
self:AddTransition( { "Boarding", "Loaded" }, "Board", "Boarding" )
self:AddTransition( "Boarding", "Loaded", "Loaded" )
self:AddTransition( "Loaded", "Unload", "Unboarding" )
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
self:AddTransition( { "Unboarding", "Unloaded" }, "Unloaded", "Unloaded" )
self:AddTransition( "*", "Monitor", "*" )
self:AddTransition( "*", "Follow", "Following" )
self:AddTransition( "*", "Guard", "Unloaded" )
self:AddTransition( "*", "Home", "*" )
self:AddTransition( "*", "BackHome" , "*" )
self:AddTransition( "*", "Destroyed", "Destroyed" )
--- Pickup Handler OnBefore for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] OnBeforePickup
-- @param #AI_CARGO_APC self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
-- @return #boolean
--- Pickup Handler OnAfter for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] OnAfterPickup
-- @param #AI_CARGO_APC self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
--- Pickup Trigger for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] Pickup
-- @param #AI_CARGO_APC self
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
--- Pickup Asynchronous Trigger for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] __Pickup
-- @param #AI_CARGO_APC self
-- @param #number Delay
-- @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
-- @function [parent=#AI_CARGO_APC] OnBeforeDeploy
-- @param #AI_CARGO_APC self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
-- @return #boolean
--- Deploy Handler OnAfter for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] OnAfterDeploy
-- @param #AI_CARGO_APC self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
--- Deploy Trigger for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] Deploy
-- @param #AI_CARGO_APC self
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
--- Deploy Asynchronous Trigger for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] __Deploy
-- @param #AI_CARGO_APC self
-- @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.
--- Loaded Handler OnAfter for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] OnAfterLoaded
-- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
-- @param #string From
-- @param #string Event
-- @param #string To
--- Unloaded Handler OnAfter for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] OnAfterUnloaded
-- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
-- @param #string From
-- @param #string Event
-- @param #string To
self:__Monitor( 1 )
self:SetCarrier( APC )
for _, APCUnit in pairs( APC:GetUnits() ) do
APCUnit:SetCargoBayWeightLimit()
end
self.Transporting = false
self.Relocating = false
return self
end
@ -256,16 +152,6 @@ function AI_CARGO_APC:SetCarrier( CargoCarrier )
end
function AI_CARGO_APC:IsTransporting()
return self.Transporting == true
end
function AI_CARGO_APC:IsRelocating()
return self.Relocating == true
end
--- Find a free Carrier within a range.
-- @param #AI_CARGO_APC self
-- @param Core.Point#COORDINATE Coordinate
@ -359,7 +245,7 @@ function AI_CARGO_APC:onafterMonitor( APC, From, Event, To )
if APC and APC:IsAlive() then
if self.CarrierCoordinate then
if self:IsRelocating() == true then
if self:IsTransporting() == true then
local Coordinate = APC:GetCoordinate()
self.Zone:Scan( { Object.Category.UNIT } )
if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then
@ -370,14 +256,16 @@ function AI_CARGO_APC:onafterMonitor( APC, From, Event, To )
else
if self:Is( "Loaded" ) then
-- There are enemies within combat range. Unload the CargoCarrier.
self:__Unload( 1, false )
self:__Unload( 1 )
else
if self:Is( "Unloaded" ) then
self:Follow()
end
self:F( "I am here" .. self:GetCurrentState() )
if self:Is( "Following" ) then
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
for Cargo, APCUnit in pairs( self.Carrier_Cargo ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
if Cargo:IsAlive() then
if not Cargo:IsNear( APCUnit, 40 ) then
APCUnit:RouteStop()
@ -406,249 +294,6 @@ function AI_CARGO_APC:onafterMonitor( APC, From, Event, To )
end
--- On before Load 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.
function AI_CARGO_APC:onbeforeLoad( APC, From, Event, To )
self:F( { APC, From, Event, To } )
local Boarding = false
if APC and APC:IsAlive() then
self.APC_Cargo = {}
for _, APCUnit in pairs( APC:GetUnits() ) do
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
local CargoBayFreeWeight = APCUnit:GetCargoBayFreeWeight()
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
--for _, Cargo in pairs( self.CargoSet:GetSet() ) do
for _, Cargo in UTILS.spairs( self.CargoSet:GetSet(), function( t, a, b ) return t[a]:GetWeight() > t[b]:GetWeight() end ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
self:F( { IsUnLoaded = Cargo:IsUnLoaded(), IsDeployed = Cargo:IsDeployed(), Cargo:GetName(), APC:GetName() } )
if Cargo:IsUnLoaded() then -- and not Cargo:IsDeployed() then
if Cargo:IsInLoadRadius( APCUnit:GetCoordinate() ) then
self:F( { "In radius", APCUnit:GetName() } )
local CargoWeight = Cargo:GetWeight()
-- 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, APCUnit )
-- 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
end
end
return Boarding
end
--- On after Board 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 Cargo.Cargo#CARGO Cargo Cargo object.
-- @param Wrapper.Unit#UNIT APCUnit
function AI_CARGO_APC:onafterBoard( APC, From, Event, To, Cargo, APCUnit )
self:F( { APC, From, Event, To, Cargo, APCUnit:GetName() } )
if APC and APC:IsAlive() then
self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), APC:GetName() } )
if not Cargo:IsLoaded() then
self:__Board( 10, Cargo, APCUnit )
else
local CargoBayFreeWeight = APCUnit:GetCargoBayFreeWeight()
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
for _, Cargo in UTILS.spairs( self.CargoSet:GetSet(), function( t, a, b ) return t[a]:GetWeight() > t[b]:GetWeight() end ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
if Cargo:IsUnLoaded() then
if Cargo:IsInLoadRadius( APCUnit:GetCoordinate() ) then
local CargoWeight = Cargo:GetWeight()
-- 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, APCUnit )
-- 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
self:__Loaded( 5, Cargo )
end
end
end
--- On before Loaded 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.
-- @return #boolean Cargo loaded.
function AI_CARGO_APC:onbeforeLoaded( APC, From, Event, To, Cargo )
self:F( { APC, From, Event, To } )
local Loaded = true
if APC and APC:IsAlive() then
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
self:F( { IsLoaded = Cargo:IsLoaded(), IsDestroyed = Cargo:IsDestroyed(), Cargo:GetName(), APC:GetName() } )
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
Loaded = false
end
end
end
if Loaded == true then
APC:RouteResume()
end
return Loaded
end
--- On after Unload 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 #boolean Deployed Cargo is deployed.
function AI_CARGO_APC:onafterUnload( APC, From, Event, To, Deployed )
self:F( { APC, From, Event, To, Deployed } )
if APC and APC:IsAlive() then
for _, APCUnit in pairs( APC:GetUnits() ) do
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
APC:RouteStop()
for _, Cargo in pairs( APCUnit:GetCargo() ) do
if Cargo:IsLoaded() then
Cargo:UnBoard()
Cargo:SetDeployed( true )
self:__Unboard( 10, Cargo, Deployed )
end
end
end
end
end
--- On after Unboard 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.
function AI_CARGO_APC:onafterUnboard( APC, From, Event, To, Cargo, Deployed )
self:F( { APC, From, Event, To, Cargo:GetName() } )
if APC and APC:IsAlive() then
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
end
--- On before 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:onbeforeUnloaded( APC, From, Event, To, Cargo, Deployed )
self:F( { APC, From, Event, To, Cargo:GetName(), Deployed = Deployed } )
local AllUnloaded = true
--Cargo:Regroup()
if APC and APC:IsAlive() then
for _, APCUnit in pairs( APC:GetUnits() ) do
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
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
self.APC_Cargo = {}
end
self:Guard()
self.CargoCarrier = APC
end
end
self:F( { AllUnloaded = AllUnloaded } )
return AllUnloaded
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
-- @param Wrapper.Group#GROUP APC
@ -660,7 +305,7 @@ function AI_CARGO_APC:onafterFollow( APC, From, Event, To )
self:F( "Follow" )
if APC and APC:IsAlive() then
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
for Cargo, APCUnit in pairs( self.Carrier_Cargo ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
if Cargo:IsUnLoaded() then
self:FollowToCarrier( self, APCUnit, Cargo )
@ -674,25 +319,25 @@ end
--- @param #AI_CARGO_APC
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC._Pickup( APC, self )
function AI_CARGO_APC._Pickup( APC, self, Coordinate, Speed, PickupZone )
APC:F( { "AI_CARGO_APC._Pickup:", APC:GetName() } )
if APC:IsAlive() then
self:Load()
self.Relocating = true
self:Load( PickupZone )
self.Relocating = false
self.Transporting = true
end
end
--- @param #AI_CARGO_APC
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC._Deploy( APC, self )
function AI_CARGO_APC._Deploy( APC, self, Coordinate, DeployZone )
APC:F( { "AI_CARGO_APC._Deploy:", APC } )
if APC:IsAlive() then
self:Unload( true )
self:Unload( DeployZone )
self.Transporting = false
self.Relocating = false
end
end
@ -707,7 +352,8 @@ end
-- @param To
-- @param Core.Point#COORDINATE Coordinate of the pickup point.
-- @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_APC:onafterPickup( APC, From, Event, To, Coordinate, Speed )
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
function AI_CARGO_APC:onafterPickup( APC, From, Event, To, Coordinate, Speed, PickupZone )
if APC and APC:IsAlive() then
@ -718,7 +364,7 @@ function AI_CARGO_APC:onafterPickup( APC, From, Event, To, Coordinate, Speed )
local Waypoints = APC:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true )
local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Pickup", self )
local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Pickup", self, Coordinate, Speed, PickupZone )
self:F({Waypoints = Waypoints})
local Waypoint = Waypoints[#Waypoints]
@ -726,10 +372,11 @@ function AI_CARGO_APC:onafterPickup( APC, From, Event, To, Coordinate, Speed )
APC:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details.
else
AI_CARGO_APC._Pickup( APC, self )
AI_CARGO_APC._Pickup( APC, self, Coordinate, Speed, PickupZone )
end
self.Transporting = true
self.Relocating = true
self.Transporting = false
end
end
@ -743,7 +390,7 @@ end
-- @param To
-- @param Core.Point#COORDINATE Coordinate Deploy place.
-- @param #number Speed Speed in km/h to drive to the depoly coordinate. Default is 50% of max possible speed the unit can go.
function AI_CARGO_APC:onafterDeploy( APC, From, Event, To, Coordinate, Speed )
function AI_CARGO_APC:onafterDeploy( APC, From, Event, To, Coordinate, Speed, DeployZone )
if APC and APC:IsAlive() then
@ -753,13 +400,16 @@ function AI_CARGO_APC:onafterDeploy( APC, From, Event, To, Coordinate, Speed )
local Waypoints = APC:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true )
local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Deploy", self )
local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Deploy", self, Coordinate, DeployZone )
self:F({Waypoints = Waypoints})
local Waypoint = Waypoints[#Waypoints]
APC:SetTaskWaypoint( Waypoint, TaskFunction ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone.
APC:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details.
self.Relocating = false
self.Transporting = true
end
end
@ -773,48 +423,21 @@ end
-- @param To
-- @param Core.Point#COORDINATE Coordinate Home place.
-- @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_APC:onafterHome( APC, From, Event, To, Coordinate, Speed )
function AI_CARGO_APC:onafterHome( APC, From, Event, To, Coordinate, Speed, HomeZone )
if APC and APC:IsAlive() ~= nil then
self.RouteHome = true
local _speed=Speed or APC:GetSpeedMax()*0.5
Speed = Speed or APC:GetSpeedMax()*0.5
local Waypoints = APC:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true )
local Waypoints = APC:TaskGroundOnRoad( Coordinate, Speed, "Line abreast", true )
self:F({Waypoints = Waypoints})
local Waypoint = Waypoints[#Waypoints]
-- Task function triggering the arrived event.
local TaskFunction = APC:TaskFunction("AI_CARGO_APC._BackHome", self)
-- Put task function on last waypoint.
APC:SetTaskWaypoint( Waypoint, TaskFunction )
APC:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details.
end
end
--- Function called when transport is back home and nothing more to do. Triggering the event BackHome.
-- @param Wrapper.Group#GROUP APC Cargo carrier.
-- @param #AI_CARGO_APC self
function AI_CARGO_APC._BackHome(APC, self)
--Trigger BackHome event.
env.info(string.format("FF APC %s is back home task function!",APC:GetName()))
APC:SmokeGreen()
self:__BackHome(1)
end
--- On after BackHome event.
-- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
-- @param From
-- @param Event
-- @param To
function AI_CARGO_APC:onafterBackHome( APC, From, Event, To )
env.info(string.format("FF APC %s is back home event!",APC:GetName()))
APC:SmokeRed()
end

View File

@ -1,4 +1,4 @@
--- **AI** -- (R2.3) - Models the intelligent transportation of infantry (cargo).
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry (cargo).
--
-- ===
--
@ -13,12 +13,39 @@
-- @extends Core.Fsm#FSM_CONTROLLABLE
--- Implements the transportation of cargo by airplanes.
--- Brings a dynamic cargo handling capability for an AI airplane group.
--
-- Airplane carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation between airbases.
--
-- The AI_CARGO_AIRPLANE module uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
-- @{Cargo.Cargo} must be declared within the mission to make AI_CARGO_AIRPLANE recognize the cargo.
-- Please consult the @{Cargo.Cargo} module for more information.
--
-- ## Cargo pickup.
--
-- Using the @{#AI_CARGO_AIRPLANE.Pickup}() method, you are able to direct the helicopters towards a point on the battlefield to board/load the cargo at the specific coordinate.
-- Ensure that the landing zone is horizontally flat, and that trees cannot be found in the landing vicinity, or the helicopters won't land or will even crash!
--
-- ## Cargo deployment.
--
-- Using the @{#AI_CARGO_AIRPLANE.Deploy}() method, you are able to direct the helicopters towards a point on the battlefield to unboard/unload the cargo at the specific coordinate.
-- Ensure that the landing zone is horizontally flat, and that trees cannot be found in the landing vicinity, or the helicopters won't land or will even crash!
--
-- ## Infantry health.
--
-- When infantry is unboarded from the APCs, the infantry is actually respawned into the battlefield.
-- As a result, the unboarding infantry is very _healthy_ every time it unboards.
-- This is due to the limitation of the DCS simulator, which is not able to specify the health of new spawned units as a parameter.
-- However, infantry that was destroyed when unboarded, won't be respawned again. Destroyed is destroyed.
-- As a result, there is some additional strength that is gained when an unboarding action happens, but in terms of simulation balance this has
-- marginal impact on the overall battlefield simulation. Fortunately, the firing strength of infantry is limited, and thus, respacing healthy infantry every
-- time is not so much of an issue ...
--
--
-- @field #AI_CARGO_AIRPLANE
AI_CARGO_AIRPLANE = {
ClassName = "AI_CARGO_AIRPLANE",
Coordinate = nil -- Core.Point#COORDINATE,
Coordinate = nil, -- Core.Point#COORDINATE
}
--- Creates a new AI_CARGO_AIRPLANE object.
@ -28,21 +55,7 @@ AI_CARGO_AIRPLANE = {
-- @return #AI_CARGO_AIRPLANE
function AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_CARGO_AIRPLANE
self.CargoSet = CargoSet -- Cargo.CargoGroup#CARGO_GROUP
self:SetStartState( "Unloaded" )
self:AddTransition( { "Unloaded", "Loaded" }, "Pickup", "*" )
self:AddTransition( "Loaded", "Deploy", "*" )
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" )
local self = BASE:Inherit( self, AI_CARGO:New( Airplane, CargoSet ) ) -- #AI_CARGO_AIRPLANE
self:AddTransition( "*", "Landed", "*" )
self:AddTransition( "*", "Home" , "*" )
@ -132,7 +145,7 @@ function AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
AirplaneUnit:SetCargoBayWeightLimit()
end
self.Relocating = false --FF should be false or set according to state of airplane!
self.Relocating = true
return self
end
@ -245,7 +258,7 @@ function AI_CARGO_AIRPLANE:onafterLanded( Airplane, From, Event, To )
-- Aircraft was sent to this airbase to pickup troops. Initiate loadling.
if self.RoutePickup == true then
env.info("FF load airplane "..Airplane:GetName())
self:Load( Airplane:GetCoordinate() )
self:Load( self.PickupZone )
self.RoutePickup = false
self.Relocating = true
end
@ -269,12 +282,15 @@ end
-- @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 Core.Point#COORDINATE Coordinate
-- @param #number Speed in km/h for travelling to pickup base.
function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Airbase, Speed )
-- @param Core.Zone#ZONE_AIRBASE PickupZone
function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Coordinate, Speed, PickupZone )
if Airplane and Airplane:IsAlive()~=nil then
env.info("FF onafterpick aircraft alive")
self.PickupZone = PickupZone
-- Get closest airbase of current position.
local ClosestAirbase, DistToAirbase=Airplane:GetCoordinate():GetClosestAirbase()
@ -288,8 +304,10 @@ function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Airbase, Sp
self.Airbase=ClosestAirbase
end
local Airbase = PickupZone:GetAirbase()
-- 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())
local Dist = Airbase:GetCoordinate():Get2DDistance(ClosestAirbase:GetCoordinate())
env.info("Distance closest to pickup airbase = "..Dist)
if Airplane:InAir() or Dist>500 then
@ -305,9 +323,6 @@ function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Airbase, Sp
-- Aircraft is on a pickup mission.
self.RoutePickup = true
-- Unclear!?
self.Transporting = true
self.Relocating = false
else
env.info("FF onafterpick calling landed")
@ -316,9 +331,13 @@ function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Airbase, Sp
self:Landed()
end
self.Transporting = false
self.Relocating = true
else
env.info("FF onafterpick aircraft not alive")
end
end
@ -328,12 +347,15 @@ end
-- @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 )
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed in km/h for travelling to pickup base.
-- @param Core.Zone#ZONE_AIRBASE DeployZone
function AI_CARGO_AIRPLANE:onafterDeploy( Airplane, From, Event, To, Coordinate, Speed, DeployZone )
if Airplane and Airplane:IsAlive()~=nil then
local Airbase = DeployZone:GetAirbase()
-- Activate uncontrolled airplane.
if Airplane:IsAlive()==false then
Airplane:SetCommand({id = 'Start', params = {}})
@ -355,116 +377,18 @@ function AI_CARGO_AIRPLANE:onafterDeploy( Airplane, From, Event, To, Airbase, Sp
end
--- On before 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:onbeforeLoad( Airplane, From, Event, To, Coordinate )
local Boarding = false
if Airplane and Airplane:IsAlive() ~= nil then
for _, AirplaneUnit in pairs( Airplane:GetUnits() ) do
local AirplaneUnit = AirplaneUnit -- Wrapper.Unit#UNIT
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
Cargo:Board( AirplaneUnit, 25 )
self:__Board( 5, Cargo, AirplaneUnit )
Boarding = true
break
end
end
end
end
end
return Boarding
end
--- On after Board event. Cargo is inside the load radius and boarding is performed.
--- On after PickedUp event. All 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.
-- @param Cargo.Cargo#CARGO Cargo Cargo object.
-- @param Wrapper.Unit#UNIT AirplaneUnit
function AI_CARGO_AIRPLANE:onafterBoard( Airplane, From, Event, To, Cargo, AirplaneUnit )
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
function AI_CARGO_AIRPLANE:onafterPickedUp( Airplane, From, Event, To, PickupZone )
self:F( { AirplaneGroup, From, Event, To } )
if Airplane and Airplane:IsAlive() then
self:F({ IsLoaded = Cargo:IsLoaded() } )
if not Cargo:IsLoaded() then
self:__Board( 10, Cargo, AirplaneUnit )
else
local CargoBayFreeWeight = AirplaneUnit:GetCargoBayFreeWeight()
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
-- Check if another cargo can be loaded into the airplane.
for _,_Cargo in UTILS.spairs( self.CargoSet:GetSet(), function( t, a, b ) return t[a]:GetWeight() > t[b]:GetWeight() end ) 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 = AirplaneUnit: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
--- 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
@ -476,7 +400,10 @@ end
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function AI_CARGO_AIRPLANE:onafterUnload( Airplane, From, Event, To )
function AI_CARGO_AIRPLANE:onafterUnload( Airplane, From, Event, To, DeployZone )
local UnboardInterval = 10
local UnboardDelay = 10
if Airplane and Airplane:IsAlive() then
for _, AirplaneUnit in pairs( Airplane:GetUnits() ) do
@ -489,68 +416,35 @@ function AI_CARGO_AIRPLANE:onafterUnload( Airplane, From, Event, To )
self:T( { CargoCarrierHeading, CargoDeployHeading } )
local CargoDeployCoordinate = Airplane:GetPointVec2():Translate( 150, CargoDeployHeading )
Cargo:UnBoard( CargoDeployCoordinate )
Cargo:__UnBoard( UnboardDelay, CargoDeployCoordinate )
UnboardDelay = UnboardDelay + UnboardInterval
Cargo:SetDeployed( true )
self:__Unboard( 10, Cargo )
self:__Unboard( UnboardDelay, Cargo, AirplaneUnit, DeployZone )
end
end
end
end
--- 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
for _, AirplaneUnit in pairs( Airplane:GetUnits() ) do
local Cargos = AirplaneUnit: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
end
--- On after Unloaded event. Cargo has been unloaded, i.e. the unboarding process is finished.
--- On after Deployed event.
-- @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 } )
function AI_CARGO_AIRPLANE:onafterDeployed( Airplane, From, Event, To, DeployZone )
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.

View File

@ -16,52 +16,360 @@
--- A dynamic cargo handling capability for AI groups.
--
-- Carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- The AI\_CARGO\_DISPATCHER module uses the @{Cargo} capabilities within the MOOSE framework, to enable Carrier GROUP objects
-- to transport @{Cargo} towards several deploy zones.
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\_DISPATCHER object recognize the cargo.
-- Please consult the @{Cargo} module for more information.
-- The AI_CARGO_DISPATCHER module uses the @{Cargo.Cargo} capabilities within the MOOSE framework, to enable Carrier GROUP objects
-- to transport @{Cargo.Cargo} towards several deploy zones.
-- @{Cargo.Cargo} must be declared within the mission to make the AI_CARGO_DISPATCHER object recognize the cargo.
-- Please consult the @{Cargo.Cargo} module for more information.
--
-- ## 1. AI\_CARGO\_DISPATCHER constructor
-- # 1) AI_CARGO_DISPATCHER constructor
--
-- * @{#AI_CARGO_DISPATCHER.New}(): Creates a new AI\_CARGO\_DISPATCHER object.
--
-- ## 2. AI\_CARGO\_DISPATCHER is a FSM
-- # 2) AI_CARGO_DISPATCHER is a FSM
--
-- ![Process](..\Presentations\AI_PATROL\Dia2.JPG)
-- This section must be read as follows. Each of the rows indicate a state transition, triggered through an event, and with an ending state of the event was executed.
-- The first column is the **From** state, the second column the **Event**, and the third column the **To** state.
--
-- ### 2.1. AI\_CARGO\_DISPATCHER States
-- So, each of the rows have the following structure.
--
-- * **From** => **Event** => **To**
--
-- Important to know is that an event can only be executed if the **current state** is the **From** state.
-- This, when an **Event** that is being triggered has a **From** state that is equal to the **Current** state of the state machine, the event will be executed,
-- and the resulting state will be the **To** state.
--
-- These are the different possible state transitions of this state machine implementation:
--
-- * Idle => Start => Monitoring
-- * Monitoring => Monitor => Monitoring
-- * Monitoring => Stop => Idle
--
-- * Monitoring => Pickup => Monitoring
-- * Monitoring => Load => Monitoring
-- * Monitoring => Loading => Monitoring
-- * Monitoring => Loaded => Monitoring
-- * Monitoring => PickedUp => Monitoring
-- * Monitoring => Deploy => Monitoring
-- * Monitoring => Unload => Monitoring
-- * Monitoring => Unloaded => Monitoring
-- * Monitoring => Deployed => Monitoring
-- * Monitoring => Home => Monitoring
--
--
-- ## 2.1) AI_CARGO_DISPATCHER States
--
-- * **Monitoring**: The process is dispatching.
-- * **Idle**: The process is idle.
--
-- ### 2.2. AI\_CARGO\_DISPATCHER Events
-- ## 2.2) AI_CARGO_DISPATCHER Events
--
-- * **Monitor**: Monitor and take action.
-- * **Start**: Start the transport process.
-- * **Stop**: Stop the transport process.
-- * **Monitor**: Monitor and take action.
--
-- * **Pickup**: Pickup cargo.
-- * **Load**: Load the cargo.
-- * **Loading**: The dispatcher is coordinating the loading of a cargo.
-- * **Loaded**: Flag that the cargo is loaded.
-- * **PickedUp**: The dispatcher has loaded all requested cargo into the CarrierGroup.
-- * **Deploy**: Deploy cargo to a location.
-- * **Unload**: Unload the cargo.
-- * **Unloaded**: Flag that the cargo is unloaded.
-- * **Deployed**: All cargo is unloaded from the carriers in the group.
-- * **Home**: A Carrier is going home.
--
-- ## 3. Set the pickup parameters.
-- # 3) Enhance your mission scripts with **Tailored** Event Handling!
--
-- Use these methods to capture the events and tailor the events with your own code!
-- All classes derived from AI_CARGO_DISPATCHER can capture these events, and you can write your own code.
--
-- In order to properly capture the events, it is mandatory that you execute the following actions using your script:
--
-- * Copy / Paste the code section into your script.
-- * Change the CLASS literal to the object name you have in your script.
-- * Within the function, you can now write your own code!
-- * IntelliSense will recognize the type of the variables provided by the function. Note: the From, Event and To variables can be safely ignored,
-- but you need to declare them as they are automatically provided by the event handling system of MOOSE.
--
-- You can send messages or fire off any other events within the code section. The sky is the limit!
--
-- ## 3.1) Tailor the **Pickup** event
--
-- Use this event handler to tailor the event when a CarrierGroup is routed towards a new pickup Coordinate and a specified Speed.
-- You can use this event handler to post messages to players, or provide status updates etc.
--
--
-- --- Pickup event handler OnAfter for CLASS.
-- -- Use this event handler to tailor the event when a CarrierGroup is routed towards a new pickup Coordinate and a specified Speed.
-- -- You can use this event handler to post messages to players, or provide status updates etc.
-- -- @param #CLASS self
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- -- @param Core.Point#COORDINATE Coordinate The coordinate of the pickup location.
-- -- @param #number Speed The velocity in meters per second on which the CarrierGroup is routed towards the pickup Coordinate.
-- -- @param Core.Zone#ZONE_AIRBASE PickupZone (optional) The zone from where the cargo is picked up. Note that the zone is optional and may not be provided, but for AI_CARGO_DISPATCHER_AIRBASE there will always be a PickupZone, as the pickup location is an airbase zone.
-- function CLASS:OnAfterPickup( From, Event, To, CarrierGroup, Coordinate, Speed, PickupZone )
--
-- -- Write here your own code.
--
-- end
--
--
-- ## 3.2) Tailor the **Load** event
--
-- Use this event handler to tailor the event when a CarrierGroup has initiated the loading or boarding of cargo within reporting or near range.
-- You can use this event handler to post messages to players, or provide status updates etc.
--
--
-- --- Load event handler OnAfter for CLASS.
-- -- Use this event handler to tailor the event when a CarrierGroup has initiated the loading or boarding of cargo within reporting or near range.
-- -- You can use this event handler to post messages to players, or provide status updates etc.
-- -- @param #CLASS self
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- -- @param Core.Zone#ZONE_AIRBASE PickupZone (optional) The zone from where the cargo is picked up. Note that the zone is optional and may not be provided, but for AI_CARGO_DISPATCHER_AIRBASE there will always be a PickupZone, as the pickup location is an airbase zone.
-- function CLASS:OnAfterLoad( From, Event, To, CarrierGroup, PickupZone )
--
-- -- Write here your own code.
--
-- end
--
--
-- ## 3.3) Tailor the **Loading** event
--
-- Use this event handler to tailor the event when a CarrierUnit of a CarrierGroup is in the process of loading or boarding of a cargo object.
-- You can use this event handler to post messages to players, or provide status updates etc.
--
--
-- --- Loading event handler OnAfter for CLASS.
-- -- Use this event handler to tailor the event when a CarrierUnit of a CarrierGroup is in the process of loading or boarding of a cargo object.
-- -- You can use this event handler to post messages to players, or provide status updates etc.
-- -- Note that this event is triggered repeatedly until all cargo (units) have been boarded into the carrier.
-- -- @param #CLASS self
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- -- @param Cargo.Cargo#CARGO Cargo The cargo object.
-- -- @param Wrapper.Unit#UNIT CarrierUnit The carrier unit that is executing the cargo loading operation.
-- -- @param Core.Zone#ZONE_AIRBASE PickupZone (optional) The zone from where the cargo is picked up. Note that the zone is optional and may not be provided, but for AI_CARGO_DISPATCHER_AIRBASE there will always be a PickupZone, as the pickup location is an airbase zone.
-- function CLASS:OnAfterLoading( From, Event, To, CarrierGroup, Cargo, CarrierUnit, PickupZone )
--
-- -- Write here your own code.
--
-- end
--
--
-- ## 3.4) Tailor the **Loaded** event
--
-- Use this event handler to tailor the event when a CarrierUnit of a CarrierGroup has loaded a cargo object.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- Note that if more cargo objects were loading or boarding into the CarrierUnit, then this event can be triggered multiple times for each different Cargo/CarrierUnit.
--
-- The function provides the CarrierGroup, which is the main group that was loading the Cargo into the CarrierUnit.
-- A CarrierUnit is part of the larger CarrierGroup.
--
--
-- --- Loaded event handler OnAfter for CLASS.
-- -- Use this event handler to tailor the event when a CarrierUnit of a CarrierGroup has loaded a cargo object.
-- -- You can use this event handler to post messages to players, or provide status updates etc.
-- -- Note that if more cargo objects were loading or boarding into the CarrierUnit, then this event can be triggered multiple times for each different Cargo/CarrierUnit.
-- -- A CarrierUnit can be part of the larger CarrierGroup.
-- -- @param #CLASS self
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- -- @param Cargo.Cargo#CARGO Cargo The cargo object.
-- -- @param Wrapper.Unit#UNIT CarrierUnit The carrier unit that is executing the cargo loading operation.
-- -- @param Core.Zone#ZONE_AIRBASE PickupZone (optional) The zone from where the cargo is picked up. Note that the zone is optional and may not be provided, but for AI_CARGO_DISPATCHER_AIRBASE there will always be a PickupZone, as the pickup location is an airbase zone.
-- function CLASS:OnAfterLoaded( From, Event, To, CarrierGroup, Cargo, CarrierUnit, PickupZone )
--
-- -- Write here your own code.
--
-- end
--
--
-- ## 3.5) Tailor the **PickedUp** event
--
-- Use this event handler to tailor the event when a carrier has picked up all cargo objects into the CarrierGroup.
-- You can use this event handler to post messages to players, or provide status updates etc.
--
--
-- --- PickedUp event handler OnAfter for CLASS.
-- -- Use this event handler to tailor the event when a carrier has picked up all cargo objects into the CarrierGroup.
-- -- You can use this event handler to post messages to players, or provide status updates etc.
-- -- @param #CLASS self
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- -- @param Core.Zone#ZONE_AIRBASE PickupZone (optional) The zone from where the cargo is picked up. Note that the zone is optional and may not be provided, but for AI_CARGO_DISPATCHER_AIRBASE there will always be a PickupZone, as the pickup location is an airbase zone.
-- function CLASS:OnAfterPickedUp( From, Event, To, CarrierGroup, PickupZone )
--
-- -- Write here your own code.
--
-- end
--
--
-- ## 3.6) Tailor the **Deploy** event
--
-- Use this event handler to tailor the event when a CarrierGroup is routed to a deploy coordinate, to Unload all cargo objects in each CarrierUnit.
-- You can use this event handler to post messages to players, or provide status updates etc.
--
--
-- --- Deploy event handler OnAfter for CLASS.
-- -- Use this event handler to tailor the event when a CarrierGroup is routed to a deploy coordinate, to Unload all cargo objects in each CarrierUnit.
-- -- You can use this event handler to post messages to players, or provide status updates etc.
-- -- @param #CLASS self
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- -- @param Core.Point#COORDINATE Coordinate The deploy coordinate.
-- -- @param #number Speed The velocity in meters per second on which the CarrierGroup is routed towards the deploy Coordinate.
-- -- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
-- function CLASS:OnAfterDeploy( From, Event, To, CarrierGroup, Coordinate, Speed, DeployZone )
--
-- -- Write here your own code.
--
-- end
--
--
-- ## 3.7) Tailor the **Unload** event
--
-- Use this event handler to tailor the event when a CarrierGroup has initiated the unloading or unboarding of cargo.
-- You can use this event handler to post messages to players, or provide status updates etc.
--
--
-- --- Unload event handler OnAfter for CLASS.
-- -- Use this event handler to tailor the event when a CarrierGroup has initiated the unloading or unboarding of cargo.
-- -- You can use this event handler to post messages to players, or provide status updates etc.
-- -- @param #CLASS self
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- -- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
-- function CLASS:OnAfterUnload( From, Event, To, CarrierGroup, DeployZone )
--
-- -- Write here your own code.
--
-- end
--
--
-- ## 3.8) Tailor the **Unloading** event
--
--
-- --- UnLoading event handler OnAfter for CLASS.
-- -- Use this event handler to tailor the event when a CarrierUnit of a CarrierGroup is in the process of unloading or unboarding of a cargo object.
-- -- You can use this event handler to post messages to players, or provide status updates etc.
-- -- Note that this event is triggered repeatedly until all cargo (units) have been unboarded from the CarrierUnit.
-- -- @param #CLASS self
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- -- @param Cargo.Cargo#CARGO Cargo The cargo object.
-- -- @param Wrapper.Unit#UNIT CarrierUnit The carrier unit that is executing the cargo unloading operation.
-- -- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
-- function CLASS:OnAfterUnload( From, Event, To, CarrierGroup, Cargo, CarrierUnit, DeployZone )
--
-- -- Write here your own code.
--
-- end
--
--
-- ## 3.9) Tailor the **Unloaded** event
--
--
-- Use this event handler to tailor the event when a CarrierUnit of a CarrierGroup has unloaded a cargo object.
-- You can use this event handler to post messages to players, or provide status updates etc.
--
-- --- Unloaded event handler OnAfter for CLASS.
-- -- Use this event handler to tailor the event when a CarrierUnit of a CarrierGroup has unloaded a cargo object.
-- -- You can use this event handler to post messages to players, or provide status updates etc.
-- -- Note that if more cargo objects were unloading or unboarding from the CarrierUnit, then this event can be triggered multiple times for each different Cargo/CarrierUnit.
-- -- A CarrierUnit can be part of the larger CarrierGroup.
-- -- @param #CLASS self
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- -- @param Cargo.Cargo#CARGO Cargo The cargo object.
-- -- @param Wrapper.Unit#UNIT CarrierUnit The carrier unit that is executing the cargo unloading operation.
-- -- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
-- function CLASS:OnAfterUnloaded( From, Event, To, CarrierGroup, Cargo, CarrierUnit, DeployZone )
--
-- -- Write here your own code.
--
-- end
--
--
-- ## 3.10) Tailor the **Deployed** event
--
-- Use this event handler to tailor the event when a carrier has deployed all cargo objects from the CarrierGroup.
-- You can use this event handler to post messages to players, or provide status updates etc.
--
--
-- --- Deployed event handler OnAfter for CLASS.
-- -- Use this event handler to tailor the event when a carrier has deployed all cargo objects from the CarrierGroup.
-- -- You can use this event handler to post messages to players, or provide status updates etc.
-- -- @param #CLASS self
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- -- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
-- function CLASS:OnAfterDeployed( From, Event, To, CarrierGroup, DeployZone )
--
-- -- Write here your own code.
--
-- end
--
-- ## 3.11) Tailor the **Home** event
--
-- Use this event handler to tailor the event when a CarrierGroup is returning to the HomeZone, after it has deployed all cargo objects from the CarrierGroup.
-- You can use this event handler to post messages to players, or provide status updates etc.
--
-- --- Home event handler OnAfter for CLASS.
-- -- Use this event handler to tailor the event when a CarrierGroup is returning to the HomeZone, after it has deployed all cargo objects from the CarrierGroup.
-- -- You can use this event handler to post messages to players, or provide status updates etc.
-- -- If there is no HomeZone is specified, the CarrierGroup will stay at the current location after having deployed all cargo and this event won't be triggered.
-- -- @param #CLASS self
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- -- @param Core.Point#COORDINATE Coordinate The home coordinate the Carrier will arrive and stop it's activities.
-- -- @param #number Speed The velocity in meters per second on which the CarrierGroup is routed towards the home Coordinate.
-- -- @param Core.Zone#ZONE HomeZone The zone wherein the carrier will return when all cargo has been transported. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
-- function CLASS:OnAfterHome( From, Event, To, CarrierGroup, Coordinate, Speed, HomeZone )
--
-- -- Write here your own code.
--
-- end
--
--
-- # 3) Set the pickup parameters.
--
-- Several parameters can be set to pickup cargo:
--
-- * @{#AI_CARGO_DISPATCHER.SetPickupRadius}(): Sets or randomizes the pickup location for the carrier around the cargo coordinate in a radius defined an outer and optional inner radius.
-- * @{#AI_CARGO_DISPATCHER.SetPickupSpeed}(): Set the speed or randomizes the speed in km/h to pickup the cargo.
--
-- ## 4. Set the deploy parameters.
-- # 4) Set the deploy parameters.
--
-- Several parameters can be set to deploy cargo:
--
-- * @{#AI_CARGO_DISPATCHER.SetDeployRadius}(): Sets or randomizes the deploy location for the carrier around the cargo coordinate in a radius defined an outer and an optional inner radius.
-- * @{#AI_CARGO_DISPATCHER.SetDeploySpeed}(): Set the speed or randomizes the speed in km/h to deploy the cargo.
--
-- ## 5. Set the home zone when there isn't any more cargo to pickup.
-- # 5) Set the home zone when there isn't any more cargo to pickup.
--
-- A home zone can be specified to where the Carriers will move when there isn't any cargo left for pickup.
-- Use @{#AI_CARGO_DISPATCHER.SetHomeZone}() to specify the home zone.
@ -74,7 +382,7 @@
AI_CARGO_DISPATCHER = {
ClassName = "AI_CARGO_DISPATCHER",
SetCarrier = nil,
DeployZonesSet = nil,
DeployZoneSet = nil,
AI_Cargo = {},
PickupCargo = {}
}
@ -114,21 +422,25 @@ function AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo )
self:AddTransition( "Monitoring", "Stop", "Idle" )
self:AddTransition( "*", "Pickup", "*" )
self:AddTransition( "*", "Loading", "*" )
self:AddTransition( "*", "Loaded", "*" )
self:AddTransition( "Monitoring", "Pickup", "Monitoring" )
self:AddTransition( "Monitoring", "Load", "Monitoring" )
self:AddTransition( "Monitoring", "Loading", "Monitoring" )
self:AddTransition( "Monitoring", "Loaded", "Monitoring" )
self:AddTransition( "Monitoring", "PickedUp", "Monitoring" )
self:AddTransition( "*", "Deploy", "*" )
self:AddTransition( "*", "Unloading", "*" )
self:AddTransition( "*", "Unloaded", "*" )
self:AddTransition( "Monitoring", "Transport", "Monitoring" )
self:AddTransition( "Monitoring", "Deploy", "Monitoring" )
self:AddTransition( "Monitoring", "Unload", "Monitoring" )
self:AddTransition( "Monitoring", "Unloading", "Monitoring" )
self:AddTransition( "Monitoring", "Unloaded", "Monitoring" )
self:AddTransition( "Monitoring", "Deployed", "Monitoring" )
self:AddTransition( "*", "Home", "*" )
self:AddTransition( "*", "RTB", "*" ) --FF
self:AddTransition( "*", "BackHome", "*" ) --FF
self:AddTransition( "Monitoring", "Home", "Monitoring" )
self.MonitorTimeInterval = 30
self.DeployInnerRadius = 200
self.DeployOuterRadius = 500
self.DeployRadiusInner = 200
self.DeployRadiusOuter = 500
self.PickupCargo = {}
self.CarrierHome = {}
@ -146,23 +458,25 @@ end
--- Creates a new AI_CARGO_DISPATCHER object.
-- @param #AI_CARGO_DISPATCHER self
-- @param Core.Set#SET_GROUP SetCarriers
-- @param Core.Set#SET_CARGO SetCargos
-- @param Core.Set#SET_ZONE DeployZonesSet
-- @param Core.Set#SET_GROUP SetCarrier
-- @param Core.Set#SET_CARGO SetCargo
-- @param Core.Set#SET_ZONE PickupZoneSet
-- @param Core.Set#SET_ZONE DeployZoneSet
-- @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()
-- DeployZoneSet = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZone )
--
function AI_CARGO_DISPATCHER:NewWithZones( SetCarriers, SetCargos, DeployZonesSet )
function AI_CARGO_DISPATCHER:NewWithZones( SetCarriers, SetCargos, PickupZoneSet, DeployZoneSet )
local self = AI_CARGO_DISPATCHER:New( SetCarriers, SetCargos ) -- #AI_CARGO_DISPATCHER
self.DeployZonesSet = DeployZonesSet
self.PickupZoneSet = PickupZoneSet
self.DeployZoneSet = DeployZoneSet
return self
end
@ -231,6 +545,19 @@ function AI_CARGO_DISPATCHER:SetHomeBase( HomeBase )
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.
-- There are two aspects that are very important to remember and take into account:
@ -356,51 +683,203 @@ end
function AI_CARGO_DISPATCHER:onafterMonitor()
for CarrierGroupName, Carrier in pairs( self.SetCarrier:GetSet() ) do
env.info("FF cargo dispatcher carrier group "..CarrierGroupName)
local Carrier = Carrier -- Wrapper.Group#GROUP
local AI_Cargo = self.AI_Cargo[Carrier]
if not AI_Cargo then
env.info("FF not AI CARGO")
-- ok, so this Carrier does not have yet an AI_CARGO handling object...
-- let's create one and also declare the Loaded and UnLoaded handlers.
self.AI_Cargo[Carrier] = self:AICargo( Carrier, self.SetCargo, self.CombatRadius )
AI_Cargo = self.AI_Cargo[Carrier]
function AI_Cargo.OnAfterPickup( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Pickup( Carrier, Cargo )
--- Pickup event handler OnAfter for AI_CARGO_DISPATCHER.
-- Use this event handler to tailor the event when a CarrierGroup is routed towards a new pickup Coordinate and a specified Speed.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterPickup
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- @param Core.Point#COORDINATE Coordinate The coordinate of the pickup location.
-- @param #number Speed The velocity in meters per second on which the CarrierGroup is routed towards the pickup Coordinate.
-- @param Core.Zone#ZONE_AIRBASE PickupZone (optional) The zone from where the cargo is picked up. Note that the zone is optional and may not be provided, but for AI_CARGO_DISPATCHER_AIRBASE there will always be a PickupZone, as the pickup location is an airbase zone.
function AI_Cargo.OnAfterPickup( AI_Cargo, CarrierGroup, From, Event, To, Coordinate, Speed, PickupZone )
self:Pickup( CarrierGroup, Coordinate, Speed, PickupZone )
end
function AI_Cargo.OnAfterLoad( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Loading( Carrier )
--- Load event handler OnAfter for AI_CARGO_DISPATCHER.
-- Use this event handler to tailor the event when a CarrierGroup has initiated the loading or boarding of cargo within reporting or near range.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterLoad
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- @param Core.Zone#ZONE_AIRBASE PickupZone (optional) The zone from where the cargo is picked up. Note that the zone is optional and may not be provided, but for AI_CARGO_DISPATCHER_AIRBASE there will always be a PickupZone, as the pickup location is an airbase zone.
function AI_Cargo.OnAfterLoad( AI_Cargo, CarrierGroup, From, Event, To, PickupZone )
self:Load( CarrierGroup, PickupZone )
end
function AI_Cargo.OnAfterLoaded( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Loaded( Carrier, Cargo )
--- Loading event handler OnAfter for AI_CARGO_DISPATCHER.
-- Use this event handler to tailor the event when a CarrierUnit of a CarrierGroup is in the process of loading or boarding of a cargo object.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- Note that this event is triggered repeatedly until all cargo (units) have been boarded into the carrier.
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterLoading
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- @param Cargo.Cargo#CARGO Cargo The cargo object.
-- @param Wrapper.Unit#UNIT CarrierUnit The carrier unit that is executing the cargo loading operation.
-- @param Core.Zone#ZONE_AIRBASE PickupZone (optional) The zone from where the cargo is picked up. Note that the zone is optional and may not be provided, but for AI_CARGO_DISPATCHER_AIRBASE there will always be a PickupZone, as the pickup location is an airbase zone.
function AI_Cargo.OnAfterBoard( AI_Cargo, CarrierGroup, From, Event, To, Cargo, CarrierUnit, PickupZone )
self:Loading( CarrierGroup, Cargo, CarrierUnit, PickupZone )
end
function AI_Cargo.OnAfterDeploy( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Deploy( Carrier, Cargo )
--- Loaded event handler OnAfter for AI_CARGO_DISPATCHER.
-- Use this event handler to tailor the event when a CarrierUnit of a CarrierGroup has loaded a cargo object.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- Note that if more cargo objects were loading or boarding into the CarrierUnit, then this event can be triggered multiple times for each different Cargo/CarrierUnit.
-- A CarrierUnit can be part of the larger CarrierGroup.
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterLoaded
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- @param Cargo.Cargo#CARGO Cargo The cargo object.
-- @param Wrapper.Unit#UNIT CarrierUnit The carrier unit that is executing the cargo loading operation.
-- @param Core.Zone#ZONE_AIRBASE PickupZone (optional) The zone from where the cargo is picked up. Note that the zone is optional and may not be provided, but for AI_CARGO_DISPATCHER_AIRBASE there will always be a PickupZone, as the pickup location is an airbase zone.
function AI_Cargo.OnAfterLoaded( AI_Cargo, CarrierGroup, From, Event, To, Cargo, CarrierUnit, PickupZone )
self:Loaded( CarrierGroup, Cargo, CarrierUnit, PickupZone )
end
--- PickedUp event handler OnAfter for AI_CARGO_DISPATCHER.
-- Use this event handler to tailor the event when a carrier has picked up all cargo objects into the CarrierGroup.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterPickedUp
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- @param Core.Zone#ZONE_AIRBASE PickupZone (optional) The zone from where the cargo is picked up. Note that the zone is optional and may not be provided, but for AI_CARGO_DISPATCHER_AIRBASE there will always be a PickupZone, as the pickup location is an airbase zone.
function AI_Cargo.OnAfterPickedUp( AI_Cargo, CarrierGroup, From, Event, To, PickupZone )
self:PickedUp( CarrierGroup, PickupZone )
self:Transport( CarrierGroup )
end
--- Deploy event handler OnAfter for AI_CARGO_DISPATCHER.
-- Use this event handler to tailor the event when a CarrierGroup is routed to a deploy coordinate, to Unload all cargo objects in each CarrierUnit.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterDeploy
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- @param Core.Point#COORDINATE Coordinate The deploy coordinate.
-- @param #number Speed The velocity in meters per second on which the CarrierGroup is routed towards the deploy Coordinate.
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
function AI_Cargo.OnAfterDeploy( AI_Cargo, CarrierGroup, From, Event, To, Coordinate, Speed, DeployZone )
self:Deploy( CarrierGroup, Coordinate, Speed, DeployZone )
end
function AI_Cargo.OnAfterUnload( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Unloading( Carrier, Cargo )
--- Unload event handler OnAfter for AI_CARGO_DISPATCHER.
-- Use this event handler to tailor the event when a CarrierGroup has initiated the unloading or unboarding of cargo.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterUnload
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
function AI_Cargo.OnAfterUnload( AI_Cargo, Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone )
self:Unloading( Carrier, Cargo, CarrierUnit, DeployZone )
end
function AI_Cargo.OnAfterUnloaded( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Unloaded( Carrier, Cargo )
end
--- UnLoading event handler OnAfter for AI_CARGO_DISPATCHER.
-- Use this event handler to tailor the event when a CarrierUnit of a CarrierGroup is in the process of unloading or unboarding of a cargo object.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- Note that this event is triggered repeatedly until all cargo (units) have been unboarded from the CarrierUnit.
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterUnloading
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- @param Cargo.Cargo#CARGO Cargo The cargo object.
-- @param Wrapper.Unit#UNIT CarrierUnit The carrier unit that is executing the cargo unloading operation.
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
-- FF added BackHome event.
function AI_Cargo.OnAfterBackHome( AI_Cargo, Carrier, From, Event, To)
self:BackHome( Carrier )
function AI_Cargo.OnAfterUnboard( AI_Cargo, CarrierGroup, From, Event, To, Cargo, CarrierUnit, DeployZone )
self:Unloading( CarrierGroup, Cargo, CarrierUnit, DeployZone )
end
--- Unloaded event handler OnAfter for AI_CARGO_DISPATCHER.
-- Use this event handler to tailor the event when a CarrierUnit of a CarrierGroup has unloaded a cargo object.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- Note that if more cargo objects were unloading or unboarding from the CarrierUnit, then this event can be triggered multiple times for each different Cargo/CarrierUnit.
-- A CarrierUnit can be part of the larger CarrierGroup.
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterUnloaded
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- @param Cargo.Cargo#CARGO Cargo The cargo object.
-- @param Wrapper.Unit#UNIT CarrierUnit The carrier unit that is executing the cargo unloading operation.
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
-- FF added RTB event.
function AI_Cargo.OnAfterRTB( AI_Cargo, Carrier, From, Event, To, Airbase)
self:RTB( Carrier, Airbase )
end
function AI_Cargo.OnAfterUnloaded( AI_Cargo, Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone )
self:Unloaded( Carrier, Cargo, CarrierUnit, DeployZone )
end
--- Deployed event handler OnAfter for AI_CARGO_DISPATCHER.
-- Use this event handler to tailor the event when a carrier has deployed all cargo objects from the CarrierGroup.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterDeployed
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
function AI_Cargo.OnAfterDeployed( AI_Cargo, Carrier, From, Event, To, DeployZone )
self:Deployed( Carrier, DeployZone )
end
--- Home event handler OnAfter for AI_CARGO_DISPATCHER.
-- Use this event handler to tailor the event when a CarrierGroup is returning to the HomeZone, after it has deployed all cargo objects from the CarrierGroup.
-- You can use this event handler to post messages to players, or provide status updates etc.
-- If there is no HomeZone is specified, the CarrierGroup will stay at the current location after having deployed all cargo.
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterHome
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- @param Wrapper.Group#GROUP CarrierGroup The group object that contains the CarrierUnits.
-- @param Core.Point#COORDINATE Coordinate The home coordinate the Carrier will arrive and stop it's activities.
-- @param #number Speed The velocity in meters per second on which the CarrierGroup is routed towards the home Coordinate.
-- @param Core.Zone#ZONE HomeZone The zone wherein the carrier will return when all cargo has been transported. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
function AI_Cargo.OnAfterHome( AI_Cargo, Carrier, From, Event, To, Coordinate, Speed, HomeZone )
self:Home( Carrier, Coordinate, Speed, HomeZone )
end
end
-- The Pickup sequence ...
@ -412,6 +891,7 @@ function AI_CARGO_DISPATCHER:onafterMonitor()
-- now find the first cargo that is Unloaded
local PickupCargo = nil
local PickupZone = nil
for CargoName, Cargo in UTILS.spairs( self.SetCargo:GetSet(), function( t, a, b ) return t[a]:GetWeight() < t[b]:GetWeight() end ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
@ -419,81 +899,53 @@ function AI_CARGO_DISPATCHER:onafterMonitor()
if Cargo:IsUnLoaded() == true and Cargo:IsDeployed() == false then
local CargoCoordinate = Cargo:GetCoordinate()
local CoordinateFree = true
for CarrierPickup, Coordinate in pairs( self.PickupCargo ) do
if CarrierPickup:IsAlive() == true then
if CargoCoordinate:Get2DDistance( Coordinate ) <= 25 then
CoordinateFree = false
PickupZone = self.PickupZoneSet and self.PickupZoneSet:IsCoordinateInZone( CargoCoordinate )
if not self.PickupZoneSet or PickupZone then
for CarrierPickup, Coordinate in pairs( self.PickupCargo ) do
if CarrierPickup:IsAlive() == true then
if CargoCoordinate:Get2DDistance( Coordinate ) <= 100 then
CoordinateFree = false
break
end
else
self.PickupCargo[CarrierPickup] = nil
end
end
if CoordinateFree == true then
-- Check if this cargo can be picked-up by at least one carrier unit of AI_Cargo.
local LargestLoadCapacity = 0
for _, Carrier in pairs( Carrier:GetUnits() ) do
local LoadCapacity = Carrier:GetCargoBayFreeWeight()
if LargestLoadCapacity < LoadCapacity then
LargestLoadCapacity = LoadCapacity
end
end
-- So if there is aa carrier that has the required load capacity to load the total weight of the cargo, dispatch the carrier.
-- Otherwise break and go to the next carrier.
-- This will skip cargo which is too large to be able to be loaded by carriers
-- and will secure an efficient dispatching scheme.
if LargestLoadCapacity >= Cargo:GetWeight() then
self.PickupCargo[Carrier] = CargoCoordinate
PickupCargo = Cargo
break
end
else
self.PickupCargo[CarrierPickup] = nil
end
end
if CoordinateFree == true then
-- Check if this cargo can be picked-up by at least one carrier unit of AI_Cargo.
local LargestLoadCapacity = 0
for _, Carrier in pairs( Carrier:GetUnits() ) do
local LoadCapacity = Carrier:GetCargoBayFreeWeight()
if LargestLoadCapacity < LoadCapacity then
LargestLoadCapacity = LoadCapacity
end
end
-- So if there is aa carrier that has the required load capacity to load the total weight of the cargo, dispatch the carrier.
-- Otherwise break and go to the next carrier.
-- This will skip cargo which is too large to be able to be loaded by carriers
-- and will secure an efficient dispatching scheme.
if LargestLoadCapacity >= Cargo:GetWeight() then
self.PickupCargo[Carrier] = CargoCoordinate
PickupCargo = Cargo
break
end
end
end
end
if PickupCargo then
self.CarrierHome[Carrier] = nil
local PickupCoordinate = PickupCargo:GetCoordinate():GetRandomCoordinateInRadius( self.PickupOuterRadius, self.PickupInnerRadius )
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
AI_Cargo:Pickup( PickupCoordinate, math.random( self.PickupMinSpeed, self.PickupMaxSpeed ), PickupZone )
break
else
env.info("FF HomeZone or HomeBase?")
if self.HomeZone then
env.info("FF HomeZone! Really?")
if not self.CarrierHome[Carrier] then
env.info("FF Yes!")
self.CarrierHome[Carrier] = true
AI_Cargo:__Home( 60, self.HomeZone:GetRandomPointVec2() )
else
env.info("FF Nope!")
AI_Cargo:__Home( 60, self.HomeZone:GetRandomPointVec2(), math.random( self.PickupMinSpeed, self.PickupMaxSpeed ), self.HomeZone )
end
elseif self.HomeBase2 then
env.info("FF HomeBase! Really?")
if not self.CarrierHome[Carrier] then
env.info("FF Yes!")
self.CarrierHome[Carrier] = true
AI_Cargo:__RTB( 1, self.HomeBase )
else
env.info("FF Nope!")
end
end
end
end
end
@ -501,7 +953,7 @@ function AI_CARGO_DISPATCHER:onafterMonitor()
self:__Monitor( self.MonitorTimeInterval )
end
--- Start Handler OnBefore for AI_CARGO_DISPATCHER
--- Start event handler OnBefore for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnBeforeStart
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From
@ -509,7 +961,7 @@ end
-- @param #string To
-- @return #boolean
--- Start Handler OnAfter for AI_CARGO_DISPATCHER
--- Start event handler OnAfter for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterStart
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From
@ -529,7 +981,7 @@ function AI_CARGO_DISPATCHER:onafterStart( From, Event, To )
self:__Monitor( -1 )
end
--- Stop Handler OnBefore for AI_CARGO_DISPATCHER
--- Stop event handler OnBefore for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnBeforeStop
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From
@ -537,7 +989,7 @@ end
-- @param #string To
-- @return #boolean
--- Stop Handler OnAfter for AI_CARGO_DISPATCHER
--- Stop event handler OnAfter for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterStop
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From
@ -554,30 +1006,6 @@ end
-- @param #number Delay
--- Loaded Handler OnAfter for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterLoaded
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Wrapper.Group#GROUP Carrier Carrier object.
-- @param Cargo.Cargo#CARGO Cargo Cargo object.
--- Unloaded Handler OnAfter for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterUnloaded
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Wrapper.Group#GROUP Carrier
-- @param Cargo.Cargo#CARGO Cargo
--- Make a Carrier run for a cargo deploy action after the cargo has been loaded, by default.
-- @param #AI_CARGO_DISPATCHER self
-- @param From
@ -586,23 +1014,14 @@ end
-- @param Wrapper.Group#GROUP Carrier
-- @param Cargo.Cargo#CARGO Cargo
-- @return #AI_CARGO_DISPATCHER
function AI_CARGO_DISPATCHER:OnAfterLoaded( From, Event, To, Carrier, Cargo )
function AI_CARGO_DISPATCHER:onafterTransport( From, Event, To, Carrier, Cargo )
if self.DeployZonesSet then
local DeployZone = self.DeployZonesSet:GetRandomZone()
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.DeployZoneSet 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 ) )
local DeployZone = self.DeployZoneSet:GetRandomZone()
local DeployCoordinate = DeployZone:GetCoordinate():GetRandomCoordinateInRadius( self.DeployOuterRadius, self.DeployInnerRadius )
self.AI_Cargo[Carrier]:Deploy( DeployCoordinate, math.random( self.DeployMinSpeed, self.DeployMaxSpeed ), DeployZone )
end
end

View File

@ -1,4 +1,4 @@
--- **AI** -- Models the intelligent transportation of infantry and other cargo using APCs.
--- **AI** -- (2.4) - Models the intelligent transportation of infantry and other cargo using APCs.
--
-- **Features:**
--
@ -28,9 +28,18 @@
--- A dynamic cargo transportation capability for AI groups.
--
-- Armoured Personnel APCs (APC), Trucks, Jeeps and other carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- The AI\_CARGO\_DISPATCHER\_APC module uses the @{Cargo} capabilities within the MOOSE framework.
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\_DISPATCHER\_APC object recognize the cargo.
-- Please consult the @{Cargo} module for more information.
--
-- The AI_CARGO_DISPATCHER_APC module is derived from the AI_CARGO_DISPATCHER module.
--
-- ## Note! In order to fully understand the mechanisms of the AI_CARGO_DISPATCHER_APC class, it is recommended that you
-- **first consult and READ the documentation of the @{AI.AI_Cargo_Dispatcher} module!!!**
--
-- Especially to learn how to **Tailor the different cargo handling events**, this will be very useful!
--
-- On top, the AI_CARGO_DISPATCHER_APC class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
-- Also ensure that you fully understand how to declare and setup Cargo objects within the MOOSE framework before using this class.
-- CARGO derived objects must be declared within the mission to make the AI_CARGO_DISPATCHER_HELICOPTER object recognize the cargo.
--
--
-- ## 1. AI\_CARGO\_DISPATCHER\_APC constructor
--
@ -88,22 +97,23 @@ AI_CARGO_DISPATCHER_APC = {
--- Creates a new AI_CARGO_DISPATCHER_APC object.
-- @param #AI_CARGO_DISPATCHER_APC self
-- @param Core.Set#SET_GROUP SetAPC The collection of APC @{Wrapper.Group}s.
-- @param Core.Set#SET_CARGO SetCargo The collection of @{Cargo} derived objects.
-- @param Core.Set#SET_ZONE SetDeployZone The collection of deploy @{Zone}s, which are used to where the cargo will be deployed by the APCs.
-- @param Core.Set#SET_GROUP APCSet The collection of APC @{Wrapper.Group}s.
-- @param Core.Set#SET_CARGO CargoSet The collection of @{Cargo.Cargo} derived objects.
-- @param Core.Set#SET_ZONE PickupZoneSet (optional) The collection of pickup @{Zone}s, which are used to where the cargo can be picked up by the APCs. If nil, then cargo can be picked up everywhere.
-- @param Core.Set#SET_ZONE DeployZoneSet The collection of deploy @{Zone}s, which are used to where the cargo will be deployed by the APCs.
-- @param DCS#Distance CombatRadius The cargo will be unloaded from the APC and engage the enemy if the enemy is within CombatRadius range. The radius is in meters, the default value is 500 meters.
-- @return #AI_CARGO_DISPATCHER_APC
-- @usage
--
-- -- Create a new cargo dispatcher for the set of APCs, with a combatradius of 500.
-- SetAPC = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart()
-- SetCargo = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
-- SetDeployZone = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
-- AICargoDispatcher = AI_CARGO_DISPATCHER_APC:New( SetAPC, SetCargo, SetDeployZone, 500 )
-- APCSet = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart()
-- CargoSet = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
-- DeployZoneSet = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
-- AICargoDispatcher = AI_CARGO_DISPATCHER_APC:New( APCSet, SCargoSet, nil, DeployZoneSet, 500 )
--
function AI_CARGO_DISPATCHER_APC:New( SetAPC, SetCargo, SetDeployZone, CombatRadius )
function AI_CARGO_DISPATCHER_APC:New( APCSet, CargoSet, PickupZoneSet, DeployZoneSet, CombatRadius )
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:NewWithZones( SetAPC, SetCargo, SetDeployZone ) ) -- #AI_CARGO_DISPATCHER_APC
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:NewWithZones( APCSet, CargoSet, PickupZoneSet, DeployZoneSet ) ) -- #AI_CARGO_DISPATCHER_APC
self.CombatRadius = CombatRadius or 500
@ -116,7 +126,7 @@ function AI_CARGO_DISPATCHER_APC:New( SetAPC, SetCargo, SetDeployZone, CombatRad
end
function AI_CARGO_DISPATCHER_APC:AICargo( APC, SetCargo )
function AI_CARGO_DISPATCHER_APC:AICargo( APC, CargoSet )
return AI_CARGO_APC:New( APC, SetCargo, self.CombatRadius )
return AI_CARGO_APC:New( APC, CargoSet, self.CombatRadius )
end

View File

@ -1,5 +1,10 @@
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry and other cargo using Planes.
--
-- **Features:**
--
-- * The airplanes will fly towards the pickup airbases to pickup the cargo.
-- * The airplanes will fly towards the deploy airbases to deploy the cargo.
--
-- ===
--
-- ### Author: **FlightControl**
@ -16,9 +21,17 @@
--- 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.
-- Please consult the @{Cargo} module for more information.
--
-- The AI_CARGO_DISPATCHER_AIRPLANE module is derived from the AI_CARGO_DISPATCHER module.
--
-- ## Note! In order to fully understand the mechanisms of the AI_CARGO_DISPATCHER_AIRPLANE class, it is recommended that you
-- **first consult and READ the documentation of the @{AI.AI_Cargo_Dispatcher} module!!!**
--
-- Especially to learn how to **Tailor the different cargo handling events**, this will be very useful!
--
-- On top, the AI_CARGO_DISPATCHER_AIRPLANE class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
-- Also ensure that you fully understand how to declare and setup Cargo objects within the MOOSE framework before using this class.
-- CARGO derived objects must be declared within the mission to make the AI_CARGO_DISPATCHER_HELICOPTER object recognize the cargo.
--
--
--
@ -29,23 +42,25 @@ AI_CARGO_DISPATCHER_AIRPLANE = {
--- Creates a new AI_CARGO_DISPATCHER_AIRPLANE object.
-- @param #AI_CARGO_DISPATCHER_AIRPLANE self
-- @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.
-- @param Core.Set#SET_GROUP AirplaneSet Set of cargo transport airplanes.
-- @param Core.Set#SET_CARGO CargoSet Set of cargo, which is supposed to be transported.
-- @param Core.Zone#SET_ZONE PickupZoneSet Set of zone airbases where the cargo has to be picked up.
-- @param Core.Zone#SET_ZONE DeployZoneSet Set of zone airbases where the cargo is deployed. Choice for each cargo is random.
-- @return #AI_CARGO_DISPATCHER_AIRPLANE self
-- @usage
--
-- -- Create a new cargo dispatcher
-- 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 )
-- AirplaneSet = SET_GROUP:New():FilterPrefixes( "Airplane" ):FilterStart()
-- CargoSet = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
-- PickupZoneSet = SET_AIRBASE:New()
-- DeployZoneSet = SET_AIRBASE:New()
-- PickupZoneSet:AddZone( ZONE_AIRBASE:New( "Gudauta", AIRBASE:FindByName( AIRBASE.Caucasus.Gudauta ), 3000 ) )
-- DeployZoneSet:AddZone( ZONE_AIRBASE:New( "Sochi", AIRBASE:FindByName( AIRBASE.Caucasus.Sochi_Adler ), 3000 ) )
-- AICargoDispatcher = AI_CARGO_DISPATCHER_AIRPLANE:New( AirplaneSet, CargoSet, PickupZoneSet, DeployZoneSet )
--
function AI_CARGO_DISPATCHER_AIRPLANE:New( SetAirplanes, SetCargos, PickupAirbasesSet, DeployAirbasesSet )
function AI_CARGO_DISPATCHER_AIRPLANE:New( AirplaneSet, CargoSet, PickupZoneSet, DeployZoneSet )
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:NewWithAirbases( SetAirplanes, SetCargos, PickupAirbasesSet, DeployAirbasesSet ) ) -- #AI_CARGO_DISPATCHER_AIRPLANE
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:NewWithZones( AirplaneSet, CargoSet, PickupZoneSet, DeployZoneSet ) ) -- #AI_CARGO_DISPATCHER_AIRPLANE
self:SetDeploySpeed( 200, 150 )
self:SetPickupSpeed( 200, 150 )
@ -55,7 +70,7 @@ function AI_CARGO_DISPATCHER_AIRPLANE:New( SetAirplanes, SetCargos, PickupAirbas
return self
end
function AI_CARGO_DISPATCHER_AIRPLANE:AICargo( Airplane, SetCargo )
function AI_CARGO_DISPATCHER_AIRPLANE:AICargo( Airplane, CargoSet )
return AI_CARGO_AIRPLANE:New( Airplane, SetCargo )
return AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
end

View File

@ -1,7 +1,12 @@
--- **AI** -- Models the intelligent transportation of infantry and other cargo using Helicopters.
--
-- The @{#AI_CARGO_DISPATCHER_HELICOPTER} classes implements the dynamic dispatching of cargo transportation tasks for helicopters.
--- **AI** -- (2.4) - Models the intelligent transportation of infantry and other cargo using Helicopters.
--
-- **Features:**
--
-- * The helicopters will fly towards the pickup locations to pickup the cargo.
-- * The helicopters will fly towards the deploy zones to deploy the cargo.
-- * Precision deployment as well as randomized deployment within the deploy zones are possible.
-- * Helicopters will orbit the deploy zones when there is no space for landing until the deploy zone is free.
--
-- ===
--
-- ### Author: **FlightControl**
@ -18,9 +23,18 @@
--- A dynamic cargo handling capability for AI helicopter groups.
--
-- Helicopters can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- The AI\_CARGO\_DISPATCHER\_HELICOPTER module uses the @{Cargo} capabilities within the MOOSE framework.
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\_DISPATCHER\_HELICOPTER object recognize the cargo.
-- Please consult the @{Cargo} module for more information.
--
--
-- The AI_CARGO_DISPATCHER_HELICOPTER module is derived from the AI_CARGO_DISPATCHER module.
--
-- ## Note! In order to fully understand the mechanisms of the AI_CARGO_DISPATCHER_HELICOPTER class, it is recommended that you
-- **first consult and READ the documentation of the @{AI.AI_Cargo_Dispatcher} module!!!**
--
-- Especially to learn how to **Tailor the different cargo handling events**, this will be very useful!
--
-- On top, the AI_CARGO_DISPATCHER_HELICOPTER class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
-- Also ensure that you fully understand how to declare and setup Cargo objects within the MOOSE framework before using this class.
-- CARGO derived objects must be declared within the mission to make the AI_CARGO_DISPATCHER_HELICOPTER object recognize the cargo.
--
-- ---
--
@ -88,21 +102,22 @@ AI_CARGO_DISPATCHER_HELICOPTER = {
--- Creates a new AI_CARGO_DISPATCHER_HELICOPTER object.
-- @param #AI_CARGO_DISPATCHER_HELICOPTER self
-- @param Core.Set#SET_GROUP SetHelicopter The collection of Helicopter @{Wrapper.Group}s.
-- @param Core.Set#SET_CARGO SetCargo The collection of @{Cargo} derived objects.
-- @param Core.Set#SET_ZONE SetDeployZones The collection of deploy @{Zone}s, which are used to where the cargo will be deployed by the Helicopters.
-- @param Core.Set#SET_GROUP HelicopterSet The collection of Helicopter @{Wrapper.Group}s.
-- @param Core.Set#SET_CARGO CargoSet The collection of @{Cargo.Cargo} derived objects.
-- @param Core.Set#SET_ZONE PickupZoneSet (optional) The collection of pickup @{Zone}s, which are used to where the cargo can be picked up by the APCs. If nil, then cargo can be picked up everywhere.
-- @param Core.Set#SET_ZONE DeployZoneSet The collection of deploy @{Zone}s, which are used to where the cargo will be deployed by the Helicopters.
-- @return #AI_CARGO_DISPATCHER_HELICOPTER
-- @usage
--
-- -- Create a new cargo dispatcher
-- SetHelicopter = SET_GROUP:New():FilterPrefixes( "Helicopter" ):FilterStart()
-- SetCargo = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
-- SetDeployZone = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
-- AICargoDispatcher = AI_CARGO_DISPATCHER_HELICOPTER:New( SetHelicopter, SetCargo )
-- HelicopterSet = SET_GROUP:New():FilterPrefixes( "Helicopter" ):FilterStart()
-- CargoSet = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
-- DeployZoneSet = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
-- AICargoDispatcher = AI_CARGO_DISPATCHER_HELICOPTER:New( HelicopterSet, SetCargo, nil, DeployZoneSet )
--
function AI_CARGO_DISPATCHER_HELICOPTER:New( SetHelicopter, SetCargo, SetDeployZones )
function AI_CARGO_DISPATCHER_HELICOPTER:New( HelicopterSet, CargoSet, PickupZoneSet, DeployZoneSet )
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:NewWithZones( SetHelicopter, SetCargo, SetDeployZones ) ) -- #AI_CARGO_DISPATCHER_HELICOPTER
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:NewWithZones( HelicopterSet, CargoSet, PickupZoneSet, DeployZoneSet ) ) -- #AI_CARGO_DISPATCHER_HELICOPTER
self:SetDeploySpeed( 200, 150 )
self:SetPickupSpeed( 200, 150 )
@ -112,8 +127,8 @@ function AI_CARGO_DISPATCHER_HELICOPTER:New( SetHelicopter, SetCargo, SetDeployZ
return self
end
function AI_CARGO_DISPATCHER_HELICOPTER:AICargo( Helicopter, SetCargo )
function AI_CARGO_DISPATCHER_HELICOPTER:AICargo( Helicopter, CargoSet )
return AI_CARGO_HELICOPTER:New( Helicopter, SetCargo )
return AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
end

View File

@ -1,4 +1,4 @@
--- **AI** -- (R2.3) - Models the intelligent transportation of infantry (cargo).
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry (cargo).
--
-- ===
--
@ -13,7 +13,34 @@
-- @extends Core.Fsm#FSM_CONTROLLABLE
--- # AI\_CARGO\_TROOPS class, extends @{Core.Fsm#FSM_CONTROLLABLE}
--- Brings a dynamic cargo handling capability for an AI helicopter group.
--
-- Helicopter carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
--
-- The AI_CARGO_HELICOPTER class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
-- @{Cargo.Cargo} must be declared within the mission to make the AI_CARGO_HELICOPTER object recognize the cargo.
-- Please consult the @{Cargo.Cargo} module for more information.
--
-- ## Cargo pickup.
--
-- Using the @{#AI_CARGO_HELICOPTER.Pickup}() method, you are able to direct the helicopters towards a point on the battlefield to board/load the cargo at the specific coordinate.
-- Ensure that the landing zone is horizontally flat, and that trees cannot be found in the landing vicinity, or the helicopters won't land or will even crash!
--
-- ## Cargo deployment.
--
-- Using the @{#AI_CARGO_HELICOPTER.Deploy}() method, you are able to direct the helicopters towards a point on the battlefield to unboard/unload the cargo at the specific coordinate.
-- Ensure that the landing zone is horizontally flat, and that trees cannot be found in the landing vicinity, or the helicopters won't land or will even crash!
--
-- ## Infantry health.
--
-- When infantry is unboarded from the APCs, the infantry is actually respawned into the battlefield.
-- As a result, the unboarding infantry is very _healthy_ every time it unboards.
-- This is due to the limitation of the DCS simulator, which is not able to specify the health of new spawned units as a parameter.
-- However, infantry that was destroyed when unboarded, won't be respawned again. Destroyed is destroyed.
-- As a result, there is some additional strength that is gained when an unboarding action happens, but in terms of simulation balance this has
-- marginal impact on the overall battlefield simulation. Fortunately, the firing strength of infantry is limited, and thus, respacing healthy infantry every
-- time is not so much of an issue ...
--
--
-- ===
--
@ -21,7 +48,6 @@
AI_CARGO_HELICOPTER = {
ClassName = "AI_CARGO_HELICOPTER",
Coordinate = nil, -- Core.Point#COORDINATE,
Helicopter_Cargo = {},
}
AI_CARGO_QUEUE = {}
@ -33,10 +59,8 @@ AI_CARGO_QUEUE = {}
-- @return #AI_CARGO_HELICOPTER
function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_CARGO_HELICOPTER
local self = BASE:Inherit( self, AI_CARGO:New( Helicopter, CargoSet ) ) -- #AI_CARGO_HELICOPTER
self.CargoSet = CargoSet -- Cargo.CargoGroup#CARGO_GROUP
self.Zone = ZONE_GROUP:New( Helicopter:GetName(), Helicopter, 300 )
self:SetStartState( "Unloaded" )
@ -46,17 +70,17 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
self:AddTransition( { "Unloaded", "Loading" }, "Load", "Boarding" )
self:AddTransition( "Boarding", "Board", "Boarding" )
self:AddTransition( "Boarding", "Loaded", "Loaded" )
self:AddTransition( "Boarding", "Loaded", "Boarding" )
self:AddTransition( "Boarding", "PickedUp", "Loaded" )
self:AddTransition( "Loaded", "Unload", "Unboarding" )
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
self:AddTransition( "Unboarding", "Unloaded", "Unloaded" )
self:AddTransition( "Unboarding", "Unloaded", "Unboarding" )
self:AddTransition( "Unboarding", "Deployed", "Unloaded" )
self:AddTransition( "*", "Landed", "*" )
self:AddTransition( "*", "Queue", "*" )
self:AddTransition( "*", "Orbit" , "*" )
self:AddTransition( "*", "Home" , "*" )
self:AddTransition( "*", "RTB" , "*" )
self:AddTransition( "*", "BackHome" , "*" )
self:AddTransition( "*", "Home" , "*" )
self:AddTransition( "*", "Destroyed", "Destroyed" )
@ -235,18 +259,15 @@ 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()
self:Load( self.PickupZone )
self.RoutePickup = false
self.Relocating = true
end
end
if self.RouteDeploy == true then
local height=Helicopter:GetHeight( true )
local velocity=Helicopter:GetVelocityKMH()
env.info(string.format("FF helo in air %s, height = %d m, velocity = %d km/h", tostring(Helicopter:InAir()), height, velocity))
if height <= 10 and velocity < 10 then
self:Unload( true )
if self.RouteDeploy == true then
if Helicopter:GetHeight( true ) <= 5 and Helicopter:GetVelocityKMH() < 10 then
self:Unload( self.DeployZone )
self.RouteDeploy = false
self.Transporting = false
self.Relocating = false
@ -264,7 +285,7 @@ end
-- @param To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed
function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordinate, Speed )
function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordinate, Speed, DeployZone )
local HelicopterInZone = false
@ -273,7 +294,7 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
local Distance = Coordinate:DistanceFromPointVec2( Helicopter:GetCoordinate() )
if Distance > 2000 then
self:__Queue( -10, Coordinate )
self:__Queue( -10, Coordinate, Speed, DeployZone )
else
local ZoneFree = true
@ -322,8 +343,12 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
-- Now route the helicopter
Helicopter:Route( Route, 0 )
-- Keep the DeployZone, because when the helo has landed, we want to provide the DeployZone to the mission designer as part of the Unloaded event.
self.DeployZone = DeployZone
else
self:__Queue( -10, Coordinate )
self:__Queue( -10, Coordinate, Speed, DeployZone )
end
end
else
@ -378,127 +403,8 @@ function AI_CARGO_HELICOPTER:onafterOrbit( Helicopter, From, Event, To, Coordina
end
--- On Before event Load.
-- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @param #string From From state.
-- @param #string Event Event
-- @param #string To To state.
function AI_CARGO_HELICOPTER:onbeforeLoad( Helicopter, From, Event, To)
local Boarding = false
if Helicopter and Helicopter:IsAlive() then
self.BoardingCount = 0
if Helicopter and Helicopter:IsAlive() then
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
local HelicopterUnit = HelicopterUnit -- Wrapper.Unit#UNIT
local CargoBayFreeWeight = HelicopterUnit:GetCargoBayFreeWeight()
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
self:F( { IsUnLoaded = Cargo:IsUnLoaded() } )
if Cargo:IsUnLoaded() and not Cargo:IsDeployed() then
if Cargo:IsInLoadRadius( HelicopterUnit:GetCoordinate() ) then
self:F( { "In radius", HelicopterUnit:GetName() } )
local CargoWeight = Cargo:GetWeight()
-- 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, HelicopterUnit )
self.Helicopter_Cargo[HelicopterUnit] = Cargo
Boarding = true
break
end
end
end
end
end
end
end
return Boarding
end
--- On after Board 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.
-- @param Cargo.Cargo#CARGO Cargo Cargo object.
-- @param Wrapper.Unit#UNIT HelicopterUnit
function AI_CARGO_HELICOPTER:onafterBoard( Helicopter, From, Event, To, Cargo, HelicopterUnit )
self:F( { Helicopter, From, Event, To, Cargo, HelicopterUnit } )
if Helicopter and Helicopter:IsAlive() then
self:F({ IsLoaded = Cargo:IsLoaded() } )
if not Cargo:IsLoaded() then
self:__Board( 10, Cargo, HelicopterUnit )
else
local CargoBayFreeWeight = HelicopterUnit:GetCargoBayFreeWeight()
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
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 CargoWeight = Cargo:GetWeight()
-- 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, HelicopterUnit )
self.Helicopter_Cargo[HelicopterUnit] = Cargo
return
end
end
end
end
self:__Loaded( 1, Cargo ) -- Will only be executed when no more cargo is boarded.
end
end
end
--- 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.
--- On after PickedUp event, raised when all cargo has been loaded into the CarrierGroup.
-- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @param #string From From state.
@ -506,8 +412,9 @@ end
-- @param #string To To state.
-- @param Cargo.Cargo#CARGO Cargo Cargo object.
-- @return #boolean Cargo is loaded.
function AI_CARGO_HELICOPTER:onafterLoaded( Helicopter, From, Event, To, Cargo )
self:F( { Helicopter, From, Event, To, Cargo } )
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
function AI_CARGO_HELICOPTER:onafterPickedUp( Helicopter, From, Event, To, PickupZone )
self:F( { Helicopter, From, Event, To } )
if Helicopter and Helicopter:IsAlive() then
self.Transporting = true
@ -515,62 +422,8 @@ function AI_CARGO_HELICOPTER:onafterLoaded( Helicopter, From, Event, To, Cargo )
end
--- On after Unload event.
-- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @param #string From From state.
-- @param #string Event Event.
-- @param #boolean Deployed Cargo is deployed.
function AI_CARGO_HELICOPTER:onafterUnload( Helicopter, From, Event, To, Deployed )
if Helicopter and Helicopter:IsAlive() then
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 )
end
end
end
end
end
--- On after Unboard 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.
-- @param Cargo.Cargo#CARGO Cargo Cargo object.
-- @param #boolean Deployed Cargo is deployed.
function AI_CARGO_HELICOPTER:onafterUnboard( Helicopter, From, Event, To, Cargo, Deployed )
if Helicopter and Helicopter:IsAlive() then
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
end
--- On before Unloaded event.
--- On after Deployed event.
-- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @param #string From From state.
@ -579,45 +432,8 @@ end
-- @param Cargo.Cargo#CARGO Cargo Cargo object.
-- @param #boolean Deployed Cargo is deployed.
-- @return #boolean True if all cargo has been unloaded.
function AI_CARGO_HELICOPTER:onbeforeUnloaded( Helicopter, From, Event, To, Cargo, Deployed )
self:F( { APC, From, Event, To, Cargo:GetName(), Deployed = Deployed } )
local AllUnloaded = true
--Cargo:Regroup()
if Helicopter and Helicopter:IsAlive() then
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
local IsEmpty = HelicopterUnit:IsCargoEmpty()
self:I({ IsEmpty = IsEmpty })
if not IsEmpty then
AllUnloaded = false
break
end
end
if AllUnloaded == true then
if Deployed == true then
self.Helicopter_Cargo = {}
end
self.Helicopter = Helicopter
end
end
self:F( { AllUnloaded = AllUnloaded } )
return AllUnloaded
end
--- On after Unloaded 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.
-- @param Cargo.Cargo#CARGO Cargo Cargo object.
-- @param #boolean Deployed Cargo is deployed.
function AI_CARGO_HELICOPTER:onafterUnloaded( Helicopter, From, Event, To, Cargo, Deployed )
function AI_CARGO_HELICOPTER:onafterDeployed( Helicopter, From, Event, To, DeployZone )
self:F( { Helicopter, From, Event, To, DeployZone = DeployZone } )
self:Orbit( Helicopter:GetCoordinate(), 50 )
@ -627,7 +443,7 @@ function AI_CARGO_HELICOPTER:onafterUnloaded( Helicopter, From, Event, To, Cargo
AI_CARGO_QUEUE[Helicopter] = nil
end, Helicopter
)
end
--- On after Pickup event.
@ -638,15 +454,12 @@ end
-- @param To
-- @param Core.Point#COORDINATE Coordinate Pickup place.
-- @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:onafterPickup( Helicopter, From, Event, To, Coordinate, Speed )
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordinate, Speed, PickupZone )
if Helicopter and Helicopter:IsAlive() ~= nil then
--Helicopter:Activate()
env.info("FF route pickup")
Coordinate:MarkToAll("helo pickupcoord")
Helicopter:Activate()
self.RoutePickup = true
Coordinate.y = math.random( 50, 500 )
@ -692,7 +505,8 @@ function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordin
-- Now route the helicopter
Helicopter:Route( Route, 1 )
self.PickupZone = PickupZone
self.Transporting = true
end
@ -702,8 +516,8 @@ end
-- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP AICargoHelicopter
-- @param Core.Point#COORDINATE Coordinate Coordinate
function AI_CARGO_HELICOPTER:_Deploy( AICargoHelicopter, Coordinate )
AICargoHelicopter:__Queue( -10, Coordinate, 100 )
function AI_CARGO_HELICOPTER:_Deploy( AICargoHelicopter, Coordinate, DeployZone )
AICargoHelicopter:__Queue( -10, Coordinate, 100, DeployZone )
end
--- On after Deploy event.
@ -714,7 +528,7 @@ end
-- @param To
-- @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 )
function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordinate, Speed, DeployZone )
if Helicopter and Helicopter:IsAlive() ~= nil then
@ -759,7 +573,7 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
local Tasks = {}
Tasks[#Tasks+1] = Helicopter:TaskFunction( "AI_CARGO_HELICOPTER._Deploy", self, Coordinate )
Tasks[#Tasks+1] = Helicopter:TaskFunction( "AI_CARGO_HELICOPTER._Deploy", self, Coordinate, DeployZone )
Tasks[#Tasks+1] = Helicopter:TaskOrbitCircle( math.random( 30, 100 ), _speed, CoordinateTo:GetRandomCoordinateInRadius( 800, 500 ) )
--Tasks[#Tasks+1] = Helicopter:TaskLandAtVec2( CoordinateTo:GetVec2() )
@ -782,8 +596,9 @@ end
-- @param Event
-- @param To
-- @param Core.Point#COORDINATE Coordinate Home place.
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 80% of max possible speed the unit can go.
function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinate, Speed )
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
-- @param Core.Zone#ZONE HomeZone The zone wherein the carrier will return when all cargo has been transported. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinate, Speed, HomeZone )
if Helicopter and Helicopter:IsAlive() ~= nil then
@ -793,9 +608,9 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
--- Calculate the target route point.
Coordinate.y = math.random( 100, 500 )
Coordinate.y = math.random( 50, 200 )
local _speed=Speed or Helicopter:GetSpeedMax()*0.8
Speed = Speed or Helicopter:GetSpeedMax()*0.5
--- Create a route point of type air.
local CoordinateFrom = Helicopter:GetCoordinate()
@ -803,7 +618,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
"RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
_speed,
Speed ,
true
)
Route[#Route+1] = WaypointFrom
@ -814,7 +629,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
"RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
_speed,
Speed ,
true
)
@ -823,10 +638,11 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
--- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
Helicopter:WayPointInitialize( Route )
local Tasks = {}
local Tasks = {}
Tasks[#Tasks+1] = Helicopter:TaskLandAtVec2( CoordinateTo:GetVec2() )
Route[#Route].task = Helicopter:TaskCombo( Tasks )
Route[#Route+1] = WaypointTo
-- Now route the helicopter
@ -836,105 +652,3 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
end
--- On after RTB event. Route the helicopter from one airport or it's current position to another airbase.
-- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter Cargo helicopter.
-- @param From
-- @param Event
-- @param To
-- @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.
function AI_CARGO_HELICOPTER:onafterRTB( Helicopter, From, Event, To, Airbase, Speed)
if Helicopter and Helicopter:IsAlive() then
-- Set takeoff type.
local Takeoff = SPAWN.Takeoff.Hot
-- Get template of group.
local Template = Helicopter:GetTemplate()
-- Nil check
if Template==nil then
return
end
-- Waypoints of the route.
local Points={}
-- To point.
local AirbasePointVec2 = Airbase:GetPointVec2()
local ToWaypoint = AirbasePointVec2:WaypointAir(
POINT_VEC3.RoutePointAltType.BARO,
"Land",
"Landing",
Speed or Helicopter:GetSpeedMax()*0.8
)
ToWaypoint["airdromeId"] = Airbase:GetID()
ToWaypoint["speed_locked"] = true
-- Task function triggering the arrived event.
local TaskFunction = Helicopter:TaskFunction("AI_CARGO_HELICOPTER._BackHome", self)
-- Put task function on last waypoint.
Helicopter:SetTaskWaypoint( ToWaypoint, TaskFunction )
-- If self.Airbase~=nil then group is currently at an airbase, where it should be respawned.
if self.Airbase then
-- Second point of the route. First point is done in RespawnAtCurrentAirbase() routine.
Template.route.points[2] = ToWaypoint
-- Respawn group at the current airbase.
Helicopter:RespawnAtCurrentAirbase(Template, Takeoff, false)
else
-- From point.
local GroupPoint = Helicopter:GetVec2()
local FromWaypoint = {}
FromWaypoint.x = GroupPoint.x
FromWaypoint.y = GroupPoint.y
FromWaypoint.type = "Turning Point"
FromWaypoint.action = "Turning Point"
FromWaypoint.speed = Helicopter:GetSpeedMax()*0.8
-- The two route points.
Points[1] = FromWaypoint
Points[2] = ToWaypoint
local PointVec3 = Helicopter:GetPointVec3()
Template.x = PointVec3.x
Template.y = PointVec3.z
Template.route.points = Points
local GroupSpawned = Helicopter:Respawn(Template)
end
end
end
--- Function called when transport is back home and nothing more to do. Triggering the event BackHome.
-- @param Wrapper.Group#GROUP Helicopter Cargo helicopter.
-- @param #AI_CARGO_HELICOPTER self
function AI_CARGO_HELICOPTER._BackHome(Group, self)
env.info("FF ai cargo helicopter back home task function")
Group:SmokeRed()
--Trigger BackHome event.
self:__BackHome(1)
end
--- On after BackHome event.
-- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter Cargo helo.
-- @param From
-- @param Event
-- @param To
function AI_CARGO_HELICOPTER:onafterBackHome( Helicopter, From, Event, To )
env.info("FF ai cargo helicopter back home event")
Helicopter:SmokeRed()
end