From 81b0c3a0509ae2aba1c052d363578eaa60ffdd02 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 5 Sep 2018 06:03:56 +0200 Subject: [PATCH 01/11] Reworking cargo --- Moose Development/Moose/AI/AI_Cargo.lua | 823 ++++++++++++++++++ Moose Development/Moose/AI/AI_Cargo_APC.lua | 227 ++--- .../Moose/AI/AI_Cargo_Airplane.lua | 246 +++--- .../Moose/AI/AI_Cargo_Dispatcher.lua | 540 ++++++++++-- .../Moose/AI/AI_Cargo_Dispatcher_APC.lua | 38 +- .../Moose/AI/AI_Cargo_Dispatcher_Airplane.lua | 47 +- .../AI/AI_Cargo_Dispatcher_Helicopter.lua | 47 +- .../Moose/AI/AI_Cargo_Helicopter.lua | 175 ++-- Moose Development/Moose/Cargo/CargoGroup.lua | 4 +- Moose Development/Moose/Cargo/CargoUnit.lua | 7 +- Moose Development/Moose/Core/Set.lua | 33 +- Moose Development/Moose/Core/Zone.lua | 99 +++ 12 files changed, 1874 insertions(+), 412 deletions(-) create mode 100644 Moose Development/Moose/AI/AI_Cargo.lua diff --git a/Moose Development/Moose/AI/AI_Cargo.lua b/Moose Development/Moose/AI/AI_Cargo.lua new file mode 100644 index 000000000..3359a425e --- /dev/null +++ b/Moose Development/Moose/AI/AI_Cargo.lua @@ -0,0 +1,823 @@ +--- **AI** -- (R2.3) - Models the intelligent transportation of infantry and other cargo. +-- +-- === +-- +-- ### Author: **FlightControl** +-- +-- === +-- +-- @module AI.AI_Cargo +-- @image AI_Cargo_Dispatching.JPG + +--- @type AI_CARGO +-- @extends Core.Fsm#FSM_CONTROLLABLE + + +--- Brings a dynamic cargo handling capability for AI groups. +-- +-- Armoured Personnel Carriers (Carrier), Trucks, Jeeps and other ground based carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation. +-- The AI\_CARGO\Carrier module uses the @{Cargo} capabilities within the MOOSE framework. +-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\Carrier object recognize the cargo. +-- Please consult the @{Cargo} module for more information. +-- +-- ## Cargo loading. +-- +-- The module will load automatically cargo when the Carriers are within boarding or loading range. +-- The boarding or loading range is specified when the cargo is created in the simulation, and therefore, this range depends on the type of cargo +-- and the specified boarding range. +-- +-- ## Enemies nearby. +-- +-- When the Carriers are approaching enemy units, something special is happening. +-- The Carriers will stop moving, and the loaded infantry will unboard and follow the Carriers and will help to defend the group. +-- The carrier will hold the route once the unboarded infantry is further than 50 meters from the Carriers, +-- to ensure that the Carriers are not too far away from the following running infantry. +-- Once all enemies are cleared, the infantry will board again automatically into the Carriers. Once boarded, the Carriers will follow its pre-defined route. +-- +-- A combat range needs to be specified in meters at the @{#AI_CARGO.New}() method. +-- This combat range will trigger the unboarding of troops when enemies are within the combat range around the Carriers. +-- During my tests, I've noticed that there is a balance between ensuring that the infantry is within sufficient hit range (effectiveness) versus +-- vulnerability of the infantry. It all depends on the kind of enemies that are expected to be encountered. +-- A combat range of 350 meters to 500 meters has been proven to be the most effective and efficient. +-- +-- ## Infantry health. +-- +-- When infantry is unboarded from the Carriers, 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 and following the Carriers, 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 ... +-- +-- ## Control the Carriers on the map. +-- +-- It is possible also as a human ground commander to influence the path of the Carriers, by pointing a new path using the DCS user interface on the map. +-- In this case, the Carriers will change the direction towards its new indicated route. However, there is a catch! +-- Once the Carriers are near the enemy, and infantry is unboarded, the Carriers won't be able to hold the route until the infantry could catch up. +-- The Carriers will simply drive on and won't stop! This is a limitation in ED that prevents user actions being controlled by the scripting engine. +-- No workaround is possible on this. +-- +-- ## Cargo deployment. +-- +-- Using the @{#AI_CARGO.Deploy}() method, you are able to direct the Carriers towards a point on the battlefield to unboard/unload the cargo at the specific coordinate. +-- The Carriers will follow nearby roads as much as possible, to ensure fast and clean cargo transportation between the objects and villages in the simulation environment. +-- +-- ## Cargo pickup. +-- +-- Using the @{#AI_CARGO.Pickup}() method, you are able to direct the Carriers towards a point on the battlefield to board/load the cargo at the specific coordinate. +-- The Carriers will follow nearby roads as much as possible, to ensure fast and clean cargo transportation between the objects and villages in the simulation environment. +-- +-- +-- +-- @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, CombatRadius ) + + local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_CARGO + + 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", "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" ) + + self:AddTransition( "*", "Monitor", "*" ) + self:AddTransition( "*", "Follow", "Following" ) + self:AddTransition( "*", "Guard", "Unloaded" ) + self:AddTransition( "*", "Home", "*" ) + + self:AddTransition( "*", "Destroyed", "Destroyed" ) + + + --- 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 + + + self:__Monitor( 1 ) + + self:SetCarrier( Carrier ) + + for _, CarrierUnit in pairs( Carrier:GetUnits() ) do + CarrierUnit:SetCargoBayWeightLimit() + end + + self.Transporting = false + self.Relocating = false + + return self +end + + +--- Set the Carrier. +-- @param #AI_CARGO self +-- @param Wrapper.Group#GROUP CargoCarrier +-- @return #AI_CARGO +function AI_CARGO:SetCarrier( CargoCarrier ) + + self.CargoCarrier = CargoCarrier -- Wrapper.Group#GROUP + self.CargoCarrier:SetState( self.CargoCarrier, "AI_CARGO", self ) + + CargoCarrier:HandleEvent( EVENTS.Dead ) + CargoCarrier:HandleEvent( EVENTS.Hit ) + + function CargoCarrier:OnEventDead( EventData ) + self:F({"dead"}) + local AICargoTroops = self:GetState( self, "AI_CARGO" ) + self:F({AICargoTroops=AICargoTroops}) + if AICargoTroops then + self:F({}) + if not AICargoTroops:Is( "Loaded" ) then + -- There are enemies within combat range. Unload the CargoCarrier. + AICargoTroops:Destroyed() + end + end + end + + function CargoCarrier:OnEventHit( EventData ) + self:F({"hit"}) + local AICargoTroops = self:GetState( self, "AI_CARGO" ) + if AICargoTroops then + self:F( { OnHitLoaded = AICargoTroops:Is( "Loaded" ) } ) + if AICargoTroops:Is( "Loaded" ) or AICargoTroops:Is( "Boarding" ) then + -- There are enemies within combat range. Unload the CargoCarrier. + AICargoTroops:Unload( false ) + end + end + end + + self.Zone = ZONE_UNIT:New( self.CargoCarrier:GetName() .. "-Zone", self.CargoCarrier, self.CombatRadius ) + self.Coalition = self.CargoCarrier:GetCoalition() + + self:SetControllable( CargoCarrier ) + + self:Guard() + + return self +end + + +function AI_CARGO:IsTransporting() + + return self.Transporting == true +end + +function AI_CARGO:IsRelocating() + + return self.Relocating == true +end + +--- Find a free Carrier within a range. +-- @param #AI_CARGO self +-- @param Core.Point#COORDINATE Coordinate +-- @param #number Radius +-- @return Wrapper.Group#GROUP NewCarrier +function AI_CARGO:FindCarrier( Coordinate, Radius ) + + local CoordinateZone = ZONE_RADIUS:New( "Zone" , Coordinate:GetVec2(), Radius ) + CoordinateZone:Scan( { Object.Category.UNIT } ) + for _, DCSUnit in pairs( CoordinateZone:GetScannedUnits() ) do + local NearUnit = UNIT:Find( DCSUnit ) + self:F({NearUnit=NearUnit}) + if not NearUnit:GetState( NearUnit, "AI_CARGO" ) then + local Attributes = NearUnit:GetDesc() + self:F({Desc=Attributes}) + if NearUnit:HasAttribute( "Trucks" ) then + return NearUnit:GetGroup() + end + end + end + + return nil + +end + + + +--- Follow Infantry to the Carrier. +-- @param #AI_CARGO self +-- @param #AI_CARGO Me +-- @param Wrapper.Unit#UNIT CarrierUnit +-- @param Cargo.CargoGroup#CARGO_GROUP Cargo +-- @return #AI_CARGO +function AI_CARGO:FollowToCarrier( Me, CarrierUnit, CargoGroup ) + + local InfantryGroup = CargoGroup:GetGroup() + + self:F( { self = self:GetClassNameAndID(), InfantryGroup = InfantryGroup:GetName() } ) + + --if self:Is( "Following" ) then + + if CarrierUnit:IsAlive() then + -- We check if the Cargo is near to the CargoCarrier. + if InfantryGroup:IsPartlyInZone( ZONE_UNIT:New( "Radius", CarrierUnit, 25 ) ) then + + -- The Cargo does not need to follow the Carrier. + Me:Guard() + + else + + self:F( { InfantryGroup = InfantryGroup:GetName() } ) + + if InfantryGroup:IsAlive() then + + self:F( { InfantryGroup = InfantryGroup:GetName() } ) + + local Waypoints = {} + + -- Calculate the new Route. + local FromCoord = InfantryGroup:GetCoordinate() + local FromGround = FromCoord:WaypointGround( 10, "Diamond" ) + self:F({FromGround=FromGround}) + table.insert( Waypoints, FromGround ) + + local ToCoord = CarrierUnit:GetCoordinate():GetRandomCoordinateInRadius( 10, 5 ) + local ToGround = ToCoord:WaypointGround( 10, "Diamond" ) + self:F({ToGround=ToGround}) + table.insert( Waypoints, ToGround ) + + local TaskRoute = InfantryGroup:TaskFunction( "AI_CARGO.FollowToCarrier", Me, CarrierUnit, CargoGroup ) + + self:F({Waypoints = Waypoints}) + local Waypoint = Waypoints[#Waypoints] + InfantryGroup:SetTaskWaypoint( Waypoint, TaskRoute ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone. + + InfantryGroup:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details. + end + end + end +end + + +--- On after Monitor event. +-- @param #AI_CARGO self +-- @param Wrapper.Group#GROUP Carrier +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +function AI_CARGO:onafterMonitor( Carrier, From, Event, To ) + self:F( { Carrier, From, Event, To } ) + + if Carrier and Carrier:IsAlive() then + if self.CarrierCoordinate then + if self:IsRelocating() == true then + local Coordinate = Carrier:GetCoordinate() + self.Zone:Scan( { Object.Category.UNIT } ) + if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then + if self:Is( "Unloaded" ) or self:Is( "Following" ) then + -- There are no enemies within combat range. Load the CargoCarrier. + self:Load() + end + else + if self:Is( "Loaded" ) then + -- There are enemies within combat range. Unload the CargoCarrier. + self:__Unload( 1 ) + else + if self:Is( "Unloaded" ) then + self:Follow() + end + if self:Is( "Following" ) then + for Cargo, CarrierUnit in pairs( self.Carrier_Cargo ) do + local Cargo = Cargo -- Cargo.Cargo#CARGO + if Cargo:IsAlive() then + if not Cargo:IsNear( CarrierUnit, 40 ) then + CarrierUnit:RouteStop() + self.CarrierStopped = true + else + if self.CarrierStopped then + if Cargo:IsNear( CarrierUnit, 25 ) then + CarrierUnit:RouteResume() + self.CarrierStopped = nil + end + end + end + end + end + end + end + end + end + + end + self.CarrierCoordinate = Carrier:GetCoordinate() + end + + self:__Monitor( -5 ) + +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. + break + 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 } ) + + self.Transporting = true + 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( 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.Transporting = false + self:__Guard( 0.1 ) + +end + +--- On after Follow event. +-- @param #AI_CARGO self +-- @param Wrapper.Group#GROUP Carrier +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +function AI_CARGO:onafterFollow( Carrier, From, Event, To ) + self:F( { Carrier, From, Event, To } ) + + self:F( "Follow" ) + if Carrier and Carrier:IsAlive() then + for Cargo, CarrierUnit in pairs( self.Carrier_Cargo ) do + local Cargo = Cargo -- Cargo.Cargo#CARGO + if Cargo:IsUnLoaded() then + self:FollowToCarrier( self, CarrierUnit, Cargo ) + CarrierUnit:RouteResume() + end + end + end + +end + + +--- @param #AI_CARGO +-- @param Wrapper.Group#GROUP Carrier +function AI_CARGO._Pickup( Carrier, self, PickupZone ) + + Carrier:F( { "AI_CARGO._Pickup:", Carrier:GetName() } ) + + if Carrier:IsAlive() then + self:Load( PickupZone) + end +end + + +function AI_CARGO._Deploy( Carrier, self, Coordinate, DeployZone ) + + Carrier:F( { "AI_CARGO._Deploy:", Carrier } ) + + if Carrier:IsAlive() then + self:Unload( DeployZone ) + end +end + + + +--- On after Pickup event. +-- @param #AI_CARGO self +-- @param Wrapper.Group#GROUP Carrier +-- @param From +-- @param Event +-- @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. +-- @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:onafterPickup( Carrier, From, Event, To, Coordinate, Speed, PickupZone ) + + if Carrier and Carrier:IsAlive() then + + if Coordinate then + self.RoutePickup = true + + local _speed=Speed or Carrier:GetSpeedMax()*0.5 + + local Waypoints = Carrier:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true ) + + local TaskFunction = Carrier:TaskFunction( "AI_CARGO._Pickup", self, PickupZone ) + + self:F({Waypoints = Waypoints}) + local Waypoint = Waypoints[#Waypoints] + Carrier:SetTaskWaypoint( Waypoint, TaskFunction ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone. + + Carrier:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details. + else + AI_CARGO._Pickup( Carrier, self, PickupZone ) + end + + self.Relocating = true + self.Transporting = false + end + +end + + +--- On after Deploy event. +-- @param #AI_CARGO self +-- @param Wrapper.Group#GROUP Carrier +-- @param From +-- @param Event +-- @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:onafterDeploy( Carrier, From, Event, To, Coordinate, Speed, DeployZone ) + + if Carrier and Carrier:IsAlive() then + + self.RouteDeploy = true + + local _speed=Speed or Carrier:GetSpeedMax()*0.5 + + local Waypoints = Carrier:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true ) + + local TaskFunction = Carrier:TaskFunction( "AI_CARGO._Deploy", self, Coordinate, DeployZone ) + + self:F({Waypoints = Waypoints}) + local Waypoint = Waypoints[#Waypoints] + Carrier:SetTaskWaypoint( Waypoint, TaskFunction ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone. + + Carrier: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 + + +--- On after Home event. +-- @param #AI_CARGO self +-- @param Wrapper.Group#GROUP Carrier +-- @param From +-- @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 50% of max possible speed the unit can go. +function AI_CARGO:onafterHome( Carrier, From, Event, To, Coordinate, Speed ) + + if Carrier and Carrier:IsAlive() ~= nil then + + self.RouteHome = true + + local _speed=Speed or Carrier:GetSpeedMax()*0.5 + + local Waypoints = Carrier:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true ) + + self:F({Waypoints = Waypoints}) + local Waypoint = Waypoints[#Waypoints] + + Carrier:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details. + + end + +end diff --git a/Moose Development/Moose/AI/AI_Cargo_APC.lua b/Moose Development/Moose/AI/AI_Cargo_APC.lua index c56ee235d..ae3de6f15 100644 --- a/Moose Development/Moose/AI/AI_Cargo_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_APC.lua @@ -90,17 +90,20 @@ function AI_CARGO_APC:New( APC, CargoSet, CombatRadius ) self.CargoSet = CargoSet -- Core.Set#SET_CARGO self.CombatRadius = CombatRadius - self:SetStartState( "Unloaded" ) + 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( "Boarding", "Loaded", "Boarding" ) + self:AddTransition( "Boarding", "PickedUp", "Loaded" ) + self:AddTransition( "Loaded", "Unload", "Unboarding" ) self:AddTransition( "Unboarding", "Unboard", "Unboarding" ) - self:AddTransition( { "Unboarding", "Unloaded" }, "Unloaded", "Unloaded" ) + self:AddTransition( "Unboarding", "Unloaded", "Unboarding" ) + self:AddTransition( "Unboarding", "Deployed", "Unloaded" ) self:AddTransition( "*", "Monitor", "*" ) self:AddTransition( "*", "Follow", "Following" ) @@ -369,13 +372,13 @@ 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 if self:Is( "Following" ) then - for APCUnit, Cargo in pairs( self.APC_Cargo ) do + for Cargo, APCUnit in pairs( self.APC_Cargo ) do local Cargo = Cargo -- Cargo.Cargo#CARGO if Cargo:IsAlive() then if not Cargo:IsNear( APCUnit, 40 ) then @@ -411,11 +414,17 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -function AI_CARGO_APC:onbeforeLoad( APC, From, Event, To ) +-- @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:onbeforeLoad( APC, From, Event, To, PickupZone ) self:F( { APC, From, Event, To } ) local Boarding = false + local LoadInterval = 10 + local LoadDelay = 10 + local APC_List = {} + local APC_Weight = {} + if APC and APC:IsAlive() then self.APC_Cargo = {} for _, APCUnit in pairs( APC:GetUnits() ) do @@ -424,32 +433,65 @@ function AI_CARGO_APC:onbeforeLoad( APC, From, Event, To ) 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() } ) + APC_List[#APC_List+1] = APCUnit + APC_Weight[APCUnit] = CargoBayFreeWeight + end + + local APC_Count = #APC_List + local APC_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(), APC:GetName() } ) + + local Loaded = false + + -- Try all APCs, but start from the one according the APC_Index + for APC_Loop = 1, #APC_List do + + local APCUnit = APC_List[APC_Index] -- Wrapper.Unit#UNIT + + -- This counters loop through the available APCs. + APC_Index = APC_Index + 1 + if APC_Index > APC_Count then + APC_Index = 1 + end + 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 + if APC_Weight[APCUnit] > CargoWeight then --and CargoBayFreeVolume > CargoVolume then APC:RouteStop() --Cargo:Ungroup() - Cargo:Board( APCUnit, 25 ) - self:__Board( 1, Cargo, APCUnit ) + Cargo:__Board( LoadDelay, APCUnit, 25 ) + LoadDelay = LoadDelay + LoadInterval + self:__Board( LoadDelay, Cargo, APCUnit, PickupZone ) -- 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 + self.APC_Cargo[Cargo] = APCUnit Boarding = true + APC_Weight[APCUnit] = APC_Weight[APCUnit] - 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. + break + end + end end @@ -465,54 +507,37 @@ end -- @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 ) +-- @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:onafterBoard( APC, From, Event, To, Cargo, APCUnit, PickupZone ) 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 ) + self:__Board( 10, Cargo, APCUnit, PickupZone ) + return end end + + self:__Loaded( 10, Cargo, APCUnit, PickupZone ) end ---- On before Loaded event. +--- On after 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 ) +-- @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:onafterLoaded( APC, From, Event, To, Cargo, PickupZone ) self:F( { APC, From, Event, To } ) local Loaded = true if APC and APC:IsAlive() then - for APCUnit, Cargo in pairs( self.APC_Cargo ) do + for Cargo, APCUnit 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 @@ -521,14 +546,26 @@ function AI_CARGO_APC:onbeforeLoaded( APC, From, Event, To, Cargo ) end end - if Loaded == true then - APC:RouteResume() + if Loaded then + self:PickedUp( PickupZone ) end - return Loaded - end +--- On after PickedUp 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 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:onafterPickedUp( APC, From, Event, To, PickupZone ) + self:F( { APC, From, Event, To } ) + + self.Transporting = true + APC:RouteResume() + +end @@ -539,9 +576,12 @@ end -- @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 } ) +-- @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_APC:onafterUnload( APC, From, Event, To, DeployZone ) + self:F( { APC, From, Event, To, DeployZone } ) + + local UnboardInterval = 10 + local UnboardDelay = 10 if APC and APC:IsAlive() then for _, APCUnit in pairs( APC:GetUnits() ) do @@ -549,9 +589,10 @@ function AI_CARGO_APC:onafterUnload( APC, From, Event, To, Deployed ) APC:RouteStop() for _, Cargo in pairs( APCUnit:GetCargo() ) do if Cargo:IsLoaded() then - Cargo:UnBoard() + Cargo:__UnBoard( UnboardDelay ) + UnboardDelay = UnboardDelay + UnboardInterval Cargo:SetDeployed( true ) - self:__Unboard( 10, Cargo, Deployed ) + self:__Unboard( UnboardDelay, Cargo, APCUnit, DeployZone ) end end end @@ -566,32 +607,22 @@ end -- @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 ) +-- @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_APC:onafterUnboard( APC, From, Event, To, Cargo, APCUnit, DeployZone ) 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 ) + self:__Unboard( 10, Cargo, APCUnit, DeployZone ) + return end end + + self:Unloaded( Cargo, APCUnit, DeployZone ) end ---- On before Unloaded event. +--- On after Unloaded event. -- @param #AI_CARGO_APC self -- @param Wrapper.Group#GROUP APC -- @param #string From From state. @@ -599,9 +630,9 @@ end -- @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 } ) +-- @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_APC:onafterUnloaded( APC, From, Event, To, Cargo, APCUnit, DeployZone ) + self:F( { APC, From, Event, To, Cargo:GetName(), DeployZone = DeployZone } ) local AllUnloaded = true @@ -619,32 +650,31 @@ function AI_CARGO_APC:onbeforeUnloaded( APC, From, Event, To, Cargo, Deployed ) end if AllUnloaded == true then - if Deployed == true then + if DeployZone == true then self.APC_Cargo = {} end - self:Guard() self.CargoCarrier = APC end end - - self:F( { AllUnloaded = AllUnloaded } ) - return AllUnloaded + + if AllUnloaded == true then + self:Deployed( DeployZone ) + end end ---- On after Unloaded event. +--- On after Deployed 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 } ) +-- @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_APC:onafterDeployed( APC, From, Event, To, DeployZone ) + self:F( { APC, From, Event, To, DeployZone = DeployZone } ) self.Transporting = false + self:__Guard( 0.1 ) end @@ -659,7 +689,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.APC_Cargo ) do local Cargo = Cargo -- Cargo.Cargo#CARGO if Cargo:IsUnLoaded() then self:FollowToCarrier( self, APCUnit, Cargo ) @@ -673,26 +703,22 @@ end --- @param #AI_CARGO_APC -- @param Wrapper.Group#GROUP APC -function AI_CARGO_APC._Pickup( APC, self ) +function AI_CARGO_APC._Pickup( APC, self, PickupZone ) APC:F( { "AI_CARGO_APC._Pickup:", APC:GetName() } ) if APC:IsAlive() then - self:Load() - self.Relocating = true + self:Load( PickupZone) 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.Relocating = false + self:Unload( DeployZone ) end end @@ -706,7 +732,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 @@ -717,7 +744,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, PickupZone ) self:F({Waypoints = Waypoints}) local Waypoint = Waypoints[#Waypoints] @@ -725,10 +752,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, PickupZone ) end - - self.Transporting = true + + self.Relocating = true + self.Transporting = false end end @@ -742,7 +770,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 @@ -752,13 +780,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 diff --git a/Moose Development/Moose/AI/AI_Cargo_Airplane.lua b/Moose Development/Moose/AI/AI_Cargo_Airplane.lua index 8ce9bcb42..55e5a79fd 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Airplane.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Airplane.lua @@ -18,7 +18,8 @@ -- @field #AI_CARGO_AIRPLANE AI_CARGO_AIRPLANE = { ClassName = "AI_CARGO_AIRPLANE", - Coordinate = nil -- Core.Point#COORDINATE, + Coordinate = nil, -- Core.Point#COORDINATE + Airplane_Cargo = {}, } --- Creates a new AI_CARGO_AIRPLANE object. @@ -39,10 +40,13 @@ function AI_CARGO_AIRPLANE:New( Airplane, CargoSet ) self:AddTransition( { "Unloaded", "Boarding" }, "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( "*", "Home" , "*" ) @@ -245,7 +249,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 +273,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 +295,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 +314,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 +322,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 +338,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 = {}}) @@ -361,32 +374,42 @@ end -- @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 ) +-- @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:onbeforeLoad( Airplane, From, Event, To, PickupZone ) local Boarding = false + local LoadInterval = 10 + local LoadDelay = 10 + 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 + local CargoBayFreeWeight = AirplaneUnit: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 + self:F({Cargo:GetName()}) + local Cargo=Cargo --Cargo.Cargo#CARGO + if Cargo:IsUnLoaded() and not Cargo:IsDeployed() then + + if Cargo:IsInLoadRadius( AirplaneUnit: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( LoadDelay, AirplaneUnit, 25 ) + LoadDelay = LoadDelay + LoadInterval + self:__Board( LoadDelay, Cargo, AirplaneUnit, PickupZone ) + self.Airplane_Cargo[AirplaneUnit] = Cargo + Boarding = true + CargoBayFreeWeight = CargoBayFreeWeight - CargoWeight + end end - end - + end end end end @@ -403,68 +426,64 @@ end -- @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:onafterBoard( Airplane, From, Event, To, Cargo, AirplaneUnit, PickupZone ) 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 ) + self:__Board( 10, Cargo, AirplaneUnit, PickupZone ) + return end end + + self:__Loaded( 10, Cargo, AirplaneUnit, PickupZone ) + +end + + +--- On After 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. +-- @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:onafterLoaded( AirplaneGroup, From, Event, To, Cargo, AirplaneUnit, PickupZone ) + self:F( { AirplaneGroup, From, Event, To } ) + + local Loaded = true + + if AirplaneGroup and AirplaneGroup:IsAlive() then + for AirplaneUnit, Cargo in pairs( self.Airplane_Cargo ) do + local Cargo = Cargo -- Cargo.Cargo#CARGO + self:F( { IsLoaded = Cargo:IsLoaded(), IsDestroyed = Cargo:IsDestroyed(), Cargo:GetName(), AirplaneGroup: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 Loaded event. Cargo is inside the carrier and ready to be transported. +--- 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. -function AI_CARGO_AIRPLANE:onafterLoaded( Airplane, 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_AIRPLANE:onafterPickedUp( Airplane, From, Event, To, PickupZone ) + self:F( { AirplaneGroup, From, Event, To } ) - 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 +495,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,9 +511,10 @@ 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 @@ -504,34 +527,19 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -function AI_CARGO_AIRPLANE:onafterUnboard( Airplane, From, Event, To, Cargo ) +function AI_CARGO_AIRPLANE:onafterUnboard( Airplane, From, Event, To, Cargo, AirplaneUnit, DeployZone ) 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 + self:__Unboard( 10, Cargo, AirplaneUnit, DeployZone ) + return end end + + self:Unloaded( Cargo, AirplaneUnit, DeployZone ) + end --- On after Unloaded event. Cargo has been unloaded, i.e. the unboarding process is finished. @@ -541,16 +549,52 @@ end -- @param #string Event Event. -- @param #string To To state. -- @param Cargo.Cargo#CARGO Cargo -function AI_CARGO_AIRPLANE:onafterUnloaded( Airplane, From, Event, To, Cargo ) +function AI_CARGO_AIRPLANE:onafterUnloaded( Airplane, From, Event, To, Cargo, AirplaneUnit, DeployZone ) - self:E( { "Unloaded", Cargo } ) + local AllUnloaded = true + + if AirplaneUnit and AirplaneUnit:IsAlive() then + for _, AirplaneUnit in pairs( AirplaneUnit:GetUnits() ) do + local IsEmpty = AirplaneUnit:IsCargoEmpty() + self:I({ IsEmpty = IsEmpty }) + if not IsEmpty then + AllUnloaded = false + break + end + end + + if AllUnloaded == true then + if DeployZone then + self.Airplane_Cargo = {} + end + self.Airplane = AirplaneUnit + end + end + + if AllUnloaded == true then + self:Deployed( DeployZone ) + end + +end + + +--- 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: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. diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua index 71359203b..1ffc9b9b9 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua @@ -21,47 +21,304 @@ -- 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. -- --- ## 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) -- --- ### 2.1. AI\_CARGO\_DISPATCHER States +-- ## 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. -- * **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. -- * **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 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 fired. +-- -- @param #string Event A string that contains the "*event name*" when the event was fired. +-- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 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 fired. +-- -- @param #string Event A string that contains the "*event name*" when the event was fired. +-- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 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 fired 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 fired. +-- -- @param #string Event A string that contains the "*event name*" when the event was fired. +-- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 fired 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 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 fired 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 fired. +-- -- @param #string Event A string that contains the "*event name*" when the event was fired. +-- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 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 fired. +-- -- @param #string Event A string that contains the "*event name*" when the event was fired. +-- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 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 fired. +-- -- @param #string Event A string that contains the "*event name*" when the event was fired. +-- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 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 fired. +-- -- @param #string Event A string that contains the "*event name*" when the event was fired. +-- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 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 fired 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 fired. +-- -- @param #string Event A string that contains the "*event name*" when the event was fired. +-- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 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 fired 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 fired. +-- -- @param #string Event A string that contains the "*event name*" when the event was fired. +-- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 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 fired. +-- -- @param #string Event A string that contains the "*event name*" when the event was fired. +-- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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) 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 +331,7 @@ AI_CARGO_DISPATCHER = { ClassName = "AI_CARGO_DISPATCHER", SetCarrier = nil, - DeployZonesSet = nil, + DeployZoneSet = nil, AI_Cargo = {}, PickupCargo = {} } @@ -115,12 +372,16 @@ function AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo ) self:AddTransition( "*", "Pickup", "*" ) + self:AddTransition( "*", "Load", "*" ) self:AddTransition( "*", "Loading", "*" ) self:AddTransition( "*", "Loaded", "*" ) + self:AddTransition( "*", "PickedUp", "*" ) self:AddTransition( "*", "Deploy", "*" ) + self:AddTransition( "*", "Unload", "*" ) self:AddTransition( "*", "Unloading", "*" ) self:AddTransition( "*", "Unloaded", "*" ) + self:AddTransition( "*", "Deployed", "*" ) self:AddTransition( "*", "Home", "*" ) @@ -146,21 +407,23 @@ end -- @param #AI_CARGO_DISPATCHER self -- @param Core.Set#SET_GROUP SetCarrier -- @param Core.Set#SET_CARGO SetCargo --- @param Core.Set#SET_ZONE DeployZonesSet +-- @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 @@ -376,28 +639,174 @@ function AI_CARGO_DISPATCHER:onafterMonitor() 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 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 fired. + -- @param #string Event A string that contains the "*event name*" when the event was fired. + -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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 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 fired. + -- @param #string Event A string that contains the "*event name*" when the event was fired. + -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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 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 fired 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 fired. + -- @param #string Event A string that contains the "*event name*" when the event was fired. + -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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 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 fired 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 fired. + -- @param #string Event A string that contains the "*event name*" when the event was fired. + -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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 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 fired. + -- @param #string Event A string that contains the "*event name*" when the event was fired. + -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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 ) + end + + + --- Deploy 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 fired. + -- @param #string Event A string that contains the "*event name*" when the event was fired. + -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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 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 fired. + -- @param #string Event A string that contains the "*event name*" when the event was fired. + -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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 ) + --- UnLoading 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 fired 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 fired. + -- @param #string Event A string that contains the "*event name*" when the event was fired. + -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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 AI_Cargo.OnAfterUnboard( AI_Cargo, CarrierGroup, From, Event, To, Cargo, CarrierUnit, DeployZone ) + self:Unloading( CarrierGroup, Cargo, CarrierUnit, DeployZone ) + end + + + --- Unloaded 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 fired 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 fired. + -- @param #string Event A string that contains the "*event name*" when the event was fired. + -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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 AI_Cargo.OnAfterUnloaded( AI_Cargo, Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone ) + self:Unloaded( Carrier, Cargo, CarrierUnit, DeployZone ) + end + + --- Deployed 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 fired. + -- @param #string Event A string that contains the "*event name*" when the event was fired. + -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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 end @@ -410,6 +819,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 @@ -417,33 +827,36 @@ 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 ) <= 25 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 @@ -452,16 +865,7 @@ function AI_CARGO_DISPATCHER:onafterMonitor() 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 if self.HomeZone then @@ -564,20 +968,12 @@ end -- @return #AI_CARGO_DISPATCHER function AI_CARGO_DISPATCHER:OnAfterLoaded( 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 diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua index 1612ce2c7..0f63f2f94 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua @@ -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#AI_CARGO_DISPATCHER} !!!** +-- +-- 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} 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} 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 diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua index 300fef9ae..fc6bde8de 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua @@ -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#AI_CARGO_DISPATCHER} !!!** +-- +-- 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} 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 diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua index 26b5d9aab..61705d84d 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua @@ -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. --- +-- **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#AI_CARGO_DISPATCHER} !!!** +-- +-- 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} 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} 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 diff --git a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua index 6c9d5a15e..62cdbf43a 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua @@ -46,10 +46,12 @@ 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", "*" ) @@ -233,7 +235,7 @@ 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 @@ -241,7 +243,7 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To ) if self.RouteDeploy == true then if Helicopter:GetHeight( true ) <= 5 and Helicopter:GetVelocityKMH() < 10 then - self:Unload( true ) + self:Unload( self.DeployZone ) self.RouteDeploy = false self.Transporting = false self.Relocating = false @@ -259,7 +261,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 @@ -268,7 +270,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 @@ -317,8 +319,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 @@ -379,39 +385,42 @@ end -- @param #string From From state. -- @param #string Event Event -- @param #string To To state. -function AI_CARGO_HELICOPTER:onbeforeLoad( Helicopter, From, Event, To) +-- @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:onbeforeLoad( Helicopter, From, Event, To, PickupZone ) local Boarding = false + + local LoadInterval = 10 + local LoadDelay = 10 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 + 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 + 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( LoadDelay, HelicopterUnit, 25 ) + LoadDelay = LoadDelay + LoadInterval + self:__Board( LoadDelay, Cargo, HelicopterUnit, PickupZone ) + self.Helicopter_Cargo[HelicopterUnit] = Cargo + Boarding = true + CargoBayFreeWeight = CargoBayFreeWeight - CargoWeight end end end @@ -431,47 +440,32 @@ end -- @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 ) +-- @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:onafterBoard( Helicopter, From, Event, To, Cargo, HelicopterUnit, PickupZone ) 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. + self:__Board( 10, Cargo, HelicopterUnit, PickupZone ) + return end end + + self:__Loaded( 10, Cargo, HelicopterUnit, PickupZone ) -- Will only be executed when no more cargo is boarded. end ---- On before Loaded event. +--- On After 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 ) +-- @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:onafterLoaded( Helicopter, From, Event, To, Cargo, HelicopterUnit, PickupZone ) self:F( { Helicopter, From, Event, To } ) local Loaded = true @@ -486,14 +480,16 @@ function AI_CARGO_HELICOPTER:onbeforeLoaded( Helicopter, From, Event, To, Cargo end end - return Loaded + if Loaded then + self:PickedUp( PickupZone ) + end 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. @@ -501,8 +497,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 @@ -516,16 +513,20 @@ end -- @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 ) +function AI_CARGO_HELICOPTER:onafterUnload( Helicopter, From, Event, To, DeployZone ) + + local UnboardInterval = 10 + local UnboardDelay = 10 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:__UnBoard( UnboardDelay ) + UnboardDelay = UnboardDelay + UnboardInterval Cargo:SetDeployed( true ) - self:__Unboard( 10, Cargo, Deployed ) + self:__Unboard( UnboardDelay, Cargo, HelicopterUnit, DeployZone ) end end end @@ -542,30 +543,20 @@ end -- @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 ) +function AI_CARGO_HELICOPTER:onafterUnboard( Helicopter, From, Event, To, Cargo, HelicopterUnit, DeployZone ) 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 ) + self:__Unboard( 10, Cargo, HelicopterUnit, DeployZone ) + return end end + + self:Unloaded( Cargo, HelicopterUnit, DeployZone ) end ---- On before Unloaded event. +--- On after Unloaded event. -- @param #AI_CARGO_HELICOPTER self -- @param Wrapper.Group#GROUP Helicopter -- @param #string From From state. @@ -574,8 +565,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 } ) +function AI_CARGO_HELICOPTER:onafterUnloaded( Helicopter, From, Event, To, Cargo, HelicopterUnit, DeployZone ) + self:F( { Helicopter, From, Event, To, Cargo:GetName(), HelicopterUnit:GetName(), DeployZone = DeployZone } ) local AllUnloaded = true @@ -592,19 +583,21 @@ function AI_CARGO_HELICOPTER:onbeforeUnloaded( Helicopter, From, Event, To, Carg end if AllUnloaded == true then - if Deployed == true then + if DeployZone then self.Helicopter_Cargo = {} end self.Helicopter = Helicopter end end - self:F( { AllUnloaded = AllUnloaded } ) - return AllUnloaded + if AllUnloaded == true then + self:Deployed( DeployZone ) + end end ---- On after Unloaded event. + +--- On after Deployed event. -- @param #AI_CARGO_HELICOPTER self -- @param Wrapper.Group#GROUP Helicopter -- @param #string From From state. @@ -612,7 +605,9 @@ end -- @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 ) +-- @return #boolean True if all cargo has been unloaded. +function AI_CARGO_HELICOPTER:onafterDeployed( Helicopter, From, Event, To, DeployZone ) + self:F( { Helicopter, From, Event, To, DeployZone = DeployZone } ) self:Orbit( Helicopter:GetCoordinate(), 50 ) @@ -622,7 +617,7 @@ function AI_CARGO_HELICOPTER:onafterUnloaded( Helicopter, From, Event, To, Cargo AI_CARGO_QUEUE[Helicopter] = nil end, Helicopter ) - + end --- On after Pickup event. @@ -633,7 +628,8 @@ 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 @@ -683,7 +679,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 @@ -693,8 +690,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. @@ -705,7 +702,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 @@ -750,7 +747,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() ) diff --git a/Moose Development/Moose/Cargo/CargoGroup.lua b/Moose Development/Moose/Cargo/CargoGroup.lua index 63f9203d1..ade21edd0 100644 --- a/Moose Development/Moose/Cargo/CargoGroup.lua +++ b/Moose Development/Moose/Cargo/CargoGroup.lua @@ -333,7 +333,7 @@ do -- CARGO_GROUP -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do - self:T( { Cargo:GetName(), Cargo.current } ) + --self:T( { Cargo:GetName(), Cargo.current } ) if not Cargo:is( "Loaded" ) @@ -355,7 +355,7 @@ do -- CARGO_GROUP if not Cancelled then if not Boarded then - self:__Boarding( 1, CargoCarrier, NearRadius, ... ) + self:__Boarding( -5, CargoCarrier, NearRadius, ... ) else self:F("Group Cargo is loaded") self:__Load( 1, CargoCarrier, ... ) diff --git a/Moose Development/Moose/Cargo/CargoUnit.lua b/Moose Development/Moose/Cargo/CargoUnit.lua index 621a9a3a9..68e77ac61 100644 --- a/Moose Development/Moose/Cargo/CargoUnit.lua +++ b/Moose Development/Moose/Cargo/CargoUnit.lua @@ -285,15 +285,16 @@ do -- CARGO_UNIT -- @param Wrapper.Client#CLIENT CargoCarrier -- @param #number NearRadius Default 25 m. function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) - --self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } ) + self:F( { From, Event, To, CargoCarrier:GetName() } ) if CargoCarrier and CargoCarrier:IsAlive() and self.CargoObject and self.CargoObject:IsAlive() then - if CargoCarrier:InAir() == false then + if (CargoCarrier:IsAir() and not CargoCarrier:InAir()) or true then + local NearRadius = CargoCarrier:GetBoundingRadius( NearRadius ) + 5 if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then self:__Load( 1, CargoCarrier, ... ) else - self:__Boarding( -1, CargoCarrier, NearRadius, ... ) + self:__Boarding( -5, CargoCarrier, NearRadius, ... ) self.RunCount = self.RunCount + 1 if self.RunCount >= 40 then self.RunCount = 0 diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index 2b9c1c8b5..650c22323 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -4778,7 +4778,7 @@ function SET_ZONE:New() return self end ---- Add ZONEs to SET_ZONE. +--- Add ZONEs by a search name to SET_ZONE. -- @param Core.Set#SET_ZONE self -- @param #string AddZoneNames A single name or an array of ZONE_BASE names. -- @return self @@ -4793,6 +4793,18 @@ function SET_ZONE:AddZonesByName( AddZoneNames ) return self end +--- Add ZONEs to SET_ZONE. +-- @param Core.Set#SET_ZONE self +-- @param Core.Zone#ZONE_BASE Zone A ZONE_BASE object. +-- @return self +function SET_ZONE:AddZone( Zone ) + + self:Add( Zone:GetName(), Zone ) + + return self +end + + --- Remove ZONEs from SET_ZONE. -- @param Core.Set#SET_ZONE self -- @param Core.Zone#ZONE_BASE RemoveZoneNames A single name or an array of ZONE_BASE names. @@ -5003,3 +5015,22 @@ function SET_ZONE:OnEventDeleteZone( EventData ) --R2.1 end end end + +--- Validate if a coordinate is in one of the zones in the set. +-- Returns the ZONE object where the coordiante is located. +-- If zones overlap, the first zone that validates the test is returned. +-- @param #SET_ZONE self +-- @param Core.Point#COORDINATE Coordinate The coordinate to be searched. +-- @return Core.Zone#ZONE_BASE The zone that validates the coordinate location. +-- @return #nil No zone has been found. +function SET_ZONE:IsCoordinateInZone( Coordinate ) + + for _, Zone in pairs( self:GetSet() ) do + local Zone = Zone -- Core.Zone#ZONE_BASE + if Zone:IsCoordinateInZone( Coordinate ) then + return Zone + end + end + + return nil +end diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index fd85bb5ee..37ce7ec6f 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -1591,4 +1591,103 @@ function ZONE_POLYGON:FindByName( ZoneName ) return ZoneFound end +do -- ZONE_AIRBASE + --- @type ZONE_AIRBASE + -- @extends #ZONE_RADIUS + + + --- The ZONE_AIRBASE class defines by a zone around a @{Wrapper.Airbase#AIRBASE} with a radius. + -- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties. + -- + -- @field #ZONE_AIRBASE + ZONE_AIRBASE = { + ClassName="ZONE_AIRBASE", + } + + + + --- Constructor to create a ZONE_AIRBASE instance, taking the zone name, a zone @{Wrapper.Airbase#AIRBASE} and a radius. + -- @param #ZONE_AIRBASE self + -- @param #string ZoneName Name of the zone. + -- @param Wrapper.Airbase#AIRBASE ZoneAirbase The @{Wrapper.Airbase} as the center of the zone. + -- @param DCS#Distance Radius The radius of the zone. + -- @return #ZONE_AIRBASE self + function ZONE_AIRBASE:New( AirbaseName ) + + + local Airbase = AIRBASE:FindByName( AirbaseName ) + + local self = BASE:Inherit( self, ZONE_RADIUS:New( AirbaseName, Airbase:GetVec2(), 4000 ) ) + + self._.ZoneAirbase = Airbase + self._.ZoneVec2Cache = self._.ZoneAirbase:GetVec2() + + -- Zone objects are added to the _DATABASE and SET_ZONE objects. + _EVENTDISPATCHER:CreateEventNewZone( self ) + + return self + end + + --- Get the airbase as part of the ZONE_AIRBASE object. + -- @param #ZONE_AIRBASE self + -- @return Wrapper.Airbase#AIRBASE The airbase. + function ZONE_AIRBASE:GetAirbase() + return self._.ZoneAirbase + end + + --- Returns the current location of the @{Wrapper.Group}. + -- @param #ZONE_AIRBASE self + -- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Group} location. + function ZONE_AIRBASE:GetVec2() + self:F( self.ZoneName ) + + local ZoneVec2 = nil + + if self._.ZoneAirbase:IsAlive() then + ZoneVec2 = self._.ZoneAirbase:GetVec2() + self._.ZoneVec2Cache = ZoneVec2 + else + ZoneVec2 = self._.ZoneVec2Cache + end + + self:T( { ZoneVec2 } ) + + return ZoneVec2 + end + + --- Returns a random location within the zone of the @{Wrapper.Group}. + -- @param #ZONE_AIRBASE self + -- @return DCS#Vec2 The random location of the zone based on the @{Wrapper.Group} location. + function ZONE_AIRBASE:GetRandomVec2() + self:F( self.ZoneName ) + + local Point = {} + local Vec2 = self._.ZoneAirbase:GetVec2() + + local angle = math.random() * math.pi*2; + Point.x = Vec2.x + math.cos( angle ) * math.random() * self:GetRadius(); + Point.y = Vec2.y + math.sin( angle ) * math.random() * self:GetRadius(); + + self:T( { Point } ) + + return Point + end + + --- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. + -- @param #ZONE_AIRBASE self + -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. + -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. + -- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone. + function ZONE_AIRBASE:GetRandomPointVec2( inner, outer ) + self:F( self.ZoneName, inner, outer ) + + local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() ) + + self:T3( { PointVec2 } ) + + return PointVec2 + end + + +end From 31fba973e5465dbb559f7a61fd46e6db3083b6b9 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 5 Sep 2018 06:59:22 +0200 Subject: [PATCH 02/11] Progress --- Moose Development/Moose/AI/AI_Cargo.lua | 348 +---------------- Moose Development/Moose/AI/AI_Cargo_APC.lua | 399 +------------------- Moose Setup/Moose.files | 1 + 3 files changed, 11 insertions(+), 737 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo.lua b/Moose Development/Moose/AI/AI_Cargo.lua index 3359a425e..d2ba6f494 100644 --- a/Moose Development/Moose/AI/AI_Cargo.lua +++ b/Moose Development/Moose/AI/AI_Cargo.lua @@ -83,12 +83,12 @@ AI_CARGO = { -- @param Core.Set#SET_CARGO CargoSet -- @param #number CombatRadius -- @return #AI_CARGO -function AI_CARGO:New( Carrier, CargoSet, CombatRadius ) +function AI_CARGO:New( Carrier, CargoSet ) - local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_CARGO + local self = BASE:Inherit( self, FSM_CONTROLLABLE:New( Carrier ) ) -- #AI_CARGO self.CargoSet = CargoSet -- Core.Set#SET_CARGO - self.CombatRadius = CombatRadius + self.CargoCarrier = Carrier -- Wrapper.Group#GROUP self:SetStartState( "Unloaded" ) @@ -105,14 +105,6 @@ function AI_CARGO:New( Carrier, CargoSet, CombatRadius ) self:AddTransition( "Unboarding", "Unloaded", "Unboarding" ) self:AddTransition( "Unboarding", "Deployed", "Unloaded" ) - self:AddTransition( "*", "Monitor", "*" ) - self:AddTransition( "*", "Follow", "Following" ) - self:AddTransition( "*", "Guard", "Unloaded" ) - self:AddTransition( "*", "Home", "*" ) - - self:AddTransition( "*", "Destroyed", "Destroyed" ) - - --- Pickup Handler OnBefore for AI_CARGO -- @function [parent=#AI_CARGO] OnBeforePickup -- @param #AI_CARGO self @@ -194,11 +186,6 @@ function AI_CARGO:New( Carrier, CargoSet, CombatRadius ) -- @param #string Event -- @param #string To - - self:__Monitor( 1 ) - - self:SetCarrier( Carrier ) - for _, CarrierUnit in pairs( Carrier:GetUnits() ) do CarrierUnit:SetCargoBayWeightLimit() end @@ -210,53 +197,6 @@ function AI_CARGO:New( Carrier, CargoSet, CombatRadius ) end ---- Set the Carrier. --- @param #AI_CARGO self --- @param Wrapper.Group#GROUP CargoCarrier --- @return #AI_CARGO -function AI_CARGO:SetCarrier( CargoCarrier ) - - self.CargoCarrier = CargoCarrier -- Wrapper.Group#GROUP - self.CargoCarrier:SetState( self.CargoCarrier, "AI_CARGO", self ) - - CargoCarrier:HandleEvent( EVENTS.Dead ) - CargoCarrier:HandleEvent( EVENTS.Hit ) - - function CargoCarrier:OnEventDead( EventData ) - self:F({"dead"}) - local AICargoTroops = self:GetState( self, "AI_CARGO" ) - self:F({AICargoTroops=AICargoTroops}) - if AICargoTroops then - self:F({}) - if not AICargoTroops:Is( "Loaded" ) then - -- There are enemies within combat range. Unload the CargoCarrier. - AICargoTroops:Destroyed() - end - end - end - - function CargoCarrier:OnEventHit( EventData ) - self:F({"hit"}) - local AICargoTroops = self:GetState( self, "AI_CARGO" ) - if AICargoTroops then - self:F( { OnHitLoaded = AICargoTroops:Is( "Loaded" ) } ) - if AICargoTroops:Is( "Loaded" ) or AICargoTroops:Is( "Boarding" ) then - -- There are enemies within combat range. Unload the CargoCarrier. - AICargoTroops:Unload( false ) - end - end - end - - self.Zone = ZONE_UNIT:New( self.CargoCarrier:GetName() .. "-Zone", self.CargoCarrier, self.CombatRadius ) - self.Coalition = self.CargoCarrier:GetCoalition() - - self:SetControllable( CargoCarrier ) - - self:Guard() - - return self -end - function AI_CARGO:IsTransporting() @@ -268,144 +208,6 @@ function AI_CARGO:IsRelocating() return self.Relocating == true end ---- Find a free Carrier within a range. --- @param #AI_CARGO self --- @param Core.Point#COORDINATE Coordinate --- @param #number Radius --- @return Wrapper.Group#GROUP NewCarrier -function AI_CARGO:FindCarrier( Coordinate, Radius ) - - local CoordinateZone = ZONE_RADIUS:New( "Zone" , Coordinate:GetVec2(), Radius ) - CoordinateZone:Scan( { Object.Category.UNIT } ) - for _, DCSUnit in pairs( CoordinateZone:GetScannedUnits() ) do - local NearUnit = UNIT:Find( DCSUnit ) - self:F({NearUnit=NearUnit}) - if not NearUnit:GetState( NearUnit, "AI_CARGO" ) then - local Attributes = NearUnit:GetDesc() - self:F({Desc=Attributes}) - if NearUnit:HasAttribute( "Trucks" ) then - return NearUnit:GetGroup() - end - end - end - - return nil - -end - - - ---- Follow Infantry to the Carrier. --- @param #AI_CARGO self --- @param #AI_CARGO Me --- @param Wrapper.Unit#UNIT CarrierUnit --- @param Cargo.CargoGroup#CARGO_GROUP Cargo --- @return #AI_CARGO -function AI_CARGO:FollowToCarrier( Me, CarrierUnit, CargoGroup ) - - local InfantryGroup = CargoGroup:GetGroup() - - self:F( { self = self:GetClassNameAndID(), InfantryGroup = InfantryGroup:GetName() } ) - - --if self:Is( "Following" ) then - - if CarrierUnit:IsAlive() then - -- We check if the Cargo is near to the CargoCarrier. - if InfantryGroup:IsPartlyInZone( ZONE_UNIT:New( "Radius", CarrierUnit, 25 ) ) then - - -- The Cargo does not need to follow the Carrier. - Me:Guard() - - else - - self:F( { InfantryGroup = InfantryGroup:GetName() } ) - - if InfantryGroup:IsAlive() then - - self:F( { InfantryGroup = InfantryGroup:GetName() } ) - - local Waypoints = {} - - -- Calculate the new Route. - local FromCoord = InfantryGroup:GetCoordinate() - local FromGround = FromCoord:WaypointGround( 10, "Diamond" ) - self:F({FromGround=FromGround}) - table.insert( Waypoints, FromGround ) - - local ToCoord = CarrierUnit:GetCoordinate():GetRandomCoordinateInRadius( 10, 5 ) - local ToGround = ToCoord:WaypointGround( 10, "Diamond" ) - self:F({ToGround=ToGround}) - table.insert( Waypoints, ToGround ) - - local TaskRoute = InfantryGroup:TaskFunction( "AI_CARGO.FollowToCarrier", Me, CarrierUnit, CargoGroup ) - - self:F({Waypoints = Waypoints}) - local Waypoint = Waypoints[#Waypoints] - InfantryGroup:SetTaskWaypoint( Waypoint, TaskRoute ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone. - - InfantryGroup:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details. - end - end - end -end - - ---- On after Monitor event. --- @param #AI_CARGO self --- @param Wrapper.Group#GROUP Carrier --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AI_CARGO:onafterMonitor( Carrier, From, Event, To ) - self:F( { Carrier, From, Event, To } ) - - if Carrier and Carrier:IsAlive() then - if self.CarrierCoordinate then - if self:IsRelocating() == true then - local Coordinate = Carrier:GetCoordinate() - self.Zone:Scan( { Object.Category.UNIT } ) - if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then - if self:Is( "Unloaded" ) or self:Is( "Following" ) then - -- There are no enemies within combat range. Load the CargoCarrier. - self:Load() - end - else - if self:Is( "Loaded" ) then - -- There are enemies within combat range. Unload the CargoCarrier. - self:__Unload( 1 ) - else - if self:Is( "Unloaded" ) then - self:Follow() - end - if self:Is( "Following" ) then - for Cargo, CarrierUnit in pairs( self.Carrier_Cargo ) do - local Cargo = Cargo -- Cargo.Cargo#CARGO - if Cargo:IsAlive() then - if not Cargo:IsNear( CarrierUnit, 40 ) then - CarrierUnit:RouteStop() - self.CarrierStopped = true - else - if self.CarrierStopped then - if Cargo:IsNear( CarrierUnit, 25 ) then - CarrierUnit:RouteResume() - self.CarrierStopped = nil - end - end - end - end - end - end - end - end - end - - end - self.CarrierCoordinate = Carrier:GetCoordinate() - end - - self:__Monitor( -5 ) - -end --- On before Load event. @@ -489,7 +291,6 @@ function AI_CARGO:onbeforeLoad( Carrier, From, Event, To, PickupZone ) if not Loaded then -- If the cargo wasn't loaded in one of the carriers, then we need to stop the loading. - break end end @@ -678,146 +479,3 @@ function AI_CARGO:onafterDeployed( Carrier, From, Event, To, DeployZone ) end ---- On after Follow event. --- @param #AI_CARGO self --- @param Wrapper.Group#GROUP Carrier --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AI_CARGO:onafterFollow( Carrier, From, Event, To ) - self:F( { Carrier, From, Event, To } ) - - self:F( "Follow" ) - if Carrier and Carrier:IsAlive() then - for Cargo, CarrierUnit in pairs( self.Carrier_Cargo ) do - local Cargo = Cargo -- Cargo.Cargo#CARGO - if Cargo:IsUnLoaded() then - self:FollowToCarrier( self, CarrierUnit, Cargo ) - CarrierUnit:RouteResume() - end - end - end - -end - - ---- @param #AI_CARGO --- @param Wrapper.Group#GROUP Carrier -function AI_CARGO._Pickup( Carrier, self, PickupZone ) - - Carrier:F( { "AI_CARGO._Pickup:", Carrier:GetName() } ) - - if Carrier:IsAlive() then - self:Load( PickupZone) - end -end - - -function AI_CARGO._Deploy( Carrier, self, Coordinate, DeployZone ) - - Carrier:F( { "AI_CARGO._Deploy:", Carrier } ) - - if Carrier:IsAlive() then - self:Unload( DeployZone ) - end -end - - - ---- On after Pickup event. --- @param #AI_CARGO self --- @param Wrapper.Group#GROUP Carrier --- @param From --- @param Event --- @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. --- @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:onafterPickup( Carrier, From, Event, To, Coordinate, Speed, PickupZone ) - - if Carrier and Carrier:IsAlive() then - - if Coordinate then - self.RoutePickup = true - - local _speed=Speed or Carrier:GetSpeedMax()*0.5 - - local Waypoints = Carrier:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true ) - - local TaskFunction = Carrier:TaskFunction( "AI_CARGO._Pickup", self, PickupZone ) - - self:F({Waypoints = Waypoints}) - local Waypoint = Waypoints[#Waypoints] - Carrier:SetTaskWaypoint( Waypoint, TaskFunction ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone. - - Carrier:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details. - else - AI_CARGO._Pickup( Carrier, self, PickupZone ) - end - - self.Relocating = true - self.Transporting = false - end - -end - - ---- On after Deploy event. --- @param #AI_CARGO self --- @param Wrapper.Group#GROUP Carrier --- @param From --- @param Event --- @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:onafterDeploy( Carrier, From, Event, To, Coordinate, Speed, DeployZone ) - - if Carrier and Carrier:IsAlive() then - - self.RouteDeploy = true - - local _speed=Speed or Carrier:GetSpeedMax()*0.5 - - local Waypoints = Carrier:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true ) - - local TaskFunction = Carrier:TaskFunction( "AI_CARGO._Deploy", self, Coordinate, DeployZone ) - - self:F({Waypoints = Waypoints}) - local Waypoint = Waypoints[#Waypoints] - Carrier:SetTaskWaypoint( Waypoint, TaskFunction ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone. - - Carrier: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 - - ---- On after Home event. --- @param #AI_CARGO self --- @param Wrapper.Group#GROUP Carrier --- @param From --- @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 50% of max possible speed the unit can go. -function AI_CARGO:onafterHome( Carrier, From, Event, To, Coordinate, Speed ) - - if Carrier and Carrier:IsAlive() ~= nil then - - self.RouteHome = true - - local _speed=Speed or Carrier:GetSpeedMax()*0.5 - - local Waypoints = Carrier:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true ) - - self:F({Waypoints = Waypoints}) - local Waypoint = Waypoints[#Waypoints] - - Carrier:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details. - - end - -end diff --git a/Moose Development/Moose/AI/AI_Cargo_APC.lua b/Moose Development/Moose/AI/AI_Cargo_APC.lua index ae3de6f15..4c00f17c6 100644 --- a/Moose Development/Moose/AI/AI_Cargo_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_APC.lua @@ -10,7 +10,7 @@ -- @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. @@ -74,7 +74,6 @@ AI_CARGO_APC = { ClassName = "AI_CARGO_APC", Coordinate = nil, -- Core.Point#COORDINATE, - APC_Cargo = {}, } --- Creates a new AI_CARGO_APC object. @@ -85,26 +84,10 @@ 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", "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" ) - self:AddTransition( "*", "Monitor", "*" ) self:AddTransition( "*", "Follow", "Following" ) self:AddTransition( "*", "Guard", "Unloaded" ) @@ -112,100 +95,10 @@ function AI_CARGO_APC:New( APC, CargoSet, CombatRadius ) 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 @@ -258,16 +151,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 @@ -361,7 +244,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 @@ -378,7 +261,7 @@ function AI_CARGO_APC:onafterMonitor( APC, From, Event, To ) self:Follow() end if self:Is( "Following" ) then - for Cargo, APCUnit in pairs( self.APC_Cargo ) do + for Cargo, APCUnit in pairs( self.Carrier_Cargo ) do local Cargo = Cargo -- Cargo.Cargo#CARGO if Cargo:IsAlive() then if not Cargo:IsNear( APCUnit, 40 ) then @@ -408,276 +291,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. --- @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:onbeforeLoad( APC, From, Event, To, PickupZone ) - self:F( { APC, From, Event, To } ) - - local Boarding = false - - local LoadInterval = 10 - local LoadDelay = 10 - local APC_List = {} - local APC_Weight = {} - - 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}) - - APC_List[#APC_List+1] = APCUnit - APC_Weight[APCUnit] = CargoBayFreeWeight - end - - local APC_Count = #APC_List - local APC_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(), APC:GetName() } ) - - local Loaded = false - - -- Try all APCs, but start from the one according the APC_Index - for APC_Loop = 1, #APC_List do - - local APCUnit = APC_List[APC_Index] -- Wrapper.Unit#UNIT - - -- This counters loop through the available APCs. - APC_Index = APC_Index + 1 - if APC_Index > APC_Count then - APC_Index = 1 - end - - 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 APC_Weight[APCUnit] > CargoWeight then --and CargoBayFreeVolume > CargoVolume then - APC:RouteStop() - --Cargo:Ungroup() - Cargo:__Board( LoadDelay, APCUnit, 25 ) - LoadDelay = LoadDelay + LoadInterval - self:__Board( LoadDelay, Cargo, APCUnit, PickupZone ) - - -- 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[Cargo] = APCUnit - Boarding = true - APC_Weight[APCUnit] = APC_Weight[APCUnit] - 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. - break - 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 --- @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:onafterBoard( APC, From, Event, To, Cargo, APCUnit, PickupZone ) - 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, PickupZone ) - return - end - end - - self:__Loaded( 10, Cargo, APCUnit, PickupZone ) - -end - ---- On after 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. --- @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:onafterLoaded( APC, From, Event, To, Cargo, PickupZone ) - self:F( { APC, From, Event, To } ) - - local Loaded = true - - if APC and APC:IsAlive() then - for Cargo, APCUnit 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 then - self:PickedUp( PickupZone ) - end - -end - ---- On after PickedUp 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 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:onafterPickedUp( APC, From, Event, To, PickupZone ) - self:F( { APC, From, Event, To } ) - - self.Transporting = true - APC:RouteResume() - -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 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_APC:onafterUnload( APC, From, Event, To, DeployZone ) - self:F( { APC, From, Event, To, DeployZone } ) - - local UnboardInterval = 10 - local UnboardDelay = 10 - - 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( UnboardDelay ) - UnboardDelay = UnboardDelay + UnboardInterval - Cargo:SetDeployed( true ) - self:__Unboard( UnboardDelay, Cargo, APCUnit, DeployZone ) - 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 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_APC:onafterUnboard( APC, From, Event, To, Cargo, APCUnit, DeployZone ) - self:F( { APC, From, Event, To, Cargo:GetName() } ) - - if APC and APC:IsAlive() then - if not Cargo:IsUnLoaded() then - self:__Unboard( 10, Cargo, APCUnit, DeployZone ) - return - end - end - - self:Unloaded( Cargo, APCUnit, DeployZone ) - -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. --- @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_APC:onafterUnloaded( APC, From, Event, To, Cargo, APCUnit, DeployZone ) - self:F( { APC, From, Event, To, Cargo:GetName(), DeployZone = DeployZone } ) - - 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 DeployZone == true then - self.APC_Cargo = {} - end - self.CargoCarrier = APC - end - end - - if AllUnloaded == true then - self:Deployed( DeployZone ) - end - -end - ---- On after Deployed 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 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_APC:onafterDeployed( APC, From, Event, To, DeployZone ) - self:F( { APC, From, Event, To, DeployZone = DeployZone } ) - - self.Transporting = false - self:__Guard( 0.1 ) - -end - --- On after Follow event. -- @param #AI_CARGO_APC self -- @param Wrapper.Group#GROUP APC @@ -689,7 +302,7 @@ function AI_CARGO_APC:onafterFollow( APC, From, Event, To ) self:F( "Follow" ) if APC and APC:IsAlive() then - for Cargo, APCUnit 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 ) @@ -709,6 +322,7 @@ function AI_CARGO_APC._Pickup( APC, self, PickupZone ) if APC:IsAlive() then self:Load( PickupZone) + self.Relocating = false end end @@ -719,6 +333,7 @@ function AI_CARGO_APC._Deploy( APC, self, Coordinate, DeployZone ) if APC:IsAlive() then self:Unload( DeployZone ) + self.Transporting = false end end diff --git a/Moose Setup/Moose.files b/Moose Setup/Moose.files index d7da38110..9ef0e3f57 100644 --- a/Moose Setup/Moose.files +++ b/Moose Setup/Moose.files @@ -70,6 +70,7 @@ AI/AI_Cap.lua AI/AI_Cas.lua AI/AI_Bai.lua AI/AI_Formation.lua +AI/AI_Cargo.lua AI/AI_Cargo_APC.lua AI/AI_Cargo_Helicopter.lua AI/AI_Cargo_Airplane.lua From 01add98b7a0a639e37c9e73dbc978ea734ee05aa Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 5 Sep 2018 16:33:31 +0200 Subject: [PATCH 03/11] Improved logic --- Moose Development/Moose/AI/AI_Cargo.lua | 2 - Moose Development/Moose/AI/AI_Cargo_APC.lua | 3 + .../Moose/AI/AI_Cargo_Airplane.lua | 177 +-------------- .../Moose/AI/AI_Cargo_Helicopter.lua | 201 +----------------- .../Moose/Wrapper/Controllable.lua | 4 +- 5 files changed, 7 insertions(+), 380 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo.lua b/Moose Development/Moose/AI/AI_Cargo.lua index d2ba6f494..bd379f299 100644 --- a/Moose Development/Moose/AI/AI_Cargo.lua +++ b/Moose Development/Moose/AI/AI_Cargo.lua @@ -363,7 +363,6 @@ end function AI_CARGO:onafterPickedUp( Carrier, From, Event, To, PickupZone ) self:F( { Carrier, From, Event, To } ) - self.Transporting = true Carrier:RouteResume() end @@ -474,7 +473,6 @@ end function AI_CARGO:onafterDeployed( Carrier, From, Event, To, DeployZone ) self:F( { Carrier, From, Event, To, DeployZone = DeployZone } ) - self.Transporting = false self:__Guard( 0.1 ) end diff --git a/Moose Development/Moose/AI/AI_Cargo_APC.lua b/Moose Development/Moose/AI/AI_Cargo_APC.lua index 4c00f17c6..f991346a9 100644 --- a/Moose Development/Moose/AI/AI_Cargo_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_APC.lua @@ -263,6 +263,7 @@ function AI_CARGO_APC:onafterMonitor( APC, From, Event, To ) if self:Is( "Following" ) then 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() @@ -323,6 +324,7 @@ function AI_CARGO_APC._Pickup( APC, self, PickupZone ) if APC:IsAlive() then self:Load( PickupZone) self.Relocating = false + self.Transporting = true end end @@ -334,6 +336,7 @@ function AI_CARGO_APC._Deploy( APC, self, Coordinate, DeployZone ) if APC:IsAlive() then self:Unload( DeployZone ) self.Transporting = false + self.Relocating = false end end diff --git a/Moose Development/Moose/AI/AI_Cargo_Airplane.lua b/Moose Development/Moose/AI/AI_Cargo_Airplane.lua index 55e5a79fd..882ea6d36 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Airplane.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Airplane.lua @@ -19,7 +19,6 @@ AI_CARGO_AIRPLANE = { ClassName = "AI_CARGO_AIRPLANE", Coordinate = nil, -- Core.Point#COORDINATE - Airplane_Cargo = {}, } --- Creates a new AI_CARGO_AIRPLANE object. @@ -29,25 +28,10 @@ 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 + local self = BASE:Inherit( self, AI_CARGO:New( Airplane, CargoSet ) ) -- #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", "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" ) - self:AddTransition( "*", "Landed", "*" ) self:AddTransition( "*", "Home" , "*" ) @@ -368,110 +352,6 @@ function AI_CARGO_AIRPLANE:onafterDeploy( Airplane, From, Event, To, Coordinate, 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 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:onbeforeLoad( Airplane, From, Event, To, PickupZone ) - - - local Boarding = false - - local LoadInterval = 10 - local LoadDelay = 10 - - if Airplane and Airplane:IsAlive() ~= nil then - - for _, AirplaneUnit in pairs( Airplane:GetUnits() ) do - local AirplaneUnit = AirplaneUnit -- Wrapper.Unit#UNIT - local CargoBayFreeWeight = AirplaneUnit: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 - self:F({Cargo:GetName()}) - local Cargo=Cargo --Cargo.Cargo#CARGO - if Cargo:IsUnLoaded() and not Cargo:IsDeployed() then - - if Cargo:IsInLoadRadius( AirplaneUnit: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( LoadDelay, AirplaneUnit, 25 ) - LoadDelay = LoadDelay + LoadInterval - self:__Board( LoadDelay, Cargo, AirplaneUnit, PickupZone ) - self.Airplane_Cargo[AirplaneUnit] = Cargo - Boarding = true - CargoBayFreeWeight = CargoBayFreeWeight - CargoWeight - end - end - end - end - end - end - - return Boarding - -end - ---- On after Board event. Cargo is inside the load radius and boarding is performed. --- @param #AI_CARGO_AIRPLANE self --- @param Wrapper.Group#GROUP Airplane Cargo transport plane. --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. --- @param Cargo.Cargo#CARGO Cargo Cargo object. --- @param Wrapper.Unit#UNIT 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:onafterBoard( Airplane, From, Event, To, Cargo, AirplaneUnit, PickupZone ) - - if Airplane and Airplane:IsAlive() then - - self:F({ IsLoaded = Cargo:IsLoaded() } ) - - if not Cargo:IsLoaded() then - self:__Board( 10, Cargo, AirplaneUnit, PickupZone ) - return - end - end - - self:__Loaded( 10, Cargo, AirplaneUnit, PickupZone ) - -end - - ---- On After 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. --- @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:onafterLoaded( AirplaneGroup, From, Event, To, Cargo, AirplaneUnit, PickupZone ) - self:F( { AirplaneGroup, From, Event, To } ) - - local Loaded = true - - if AirplaneGroup and AirplaneGroup:IsAlive() then - for AirplaneUnit, Cargo in pairs( self.Airplane_Cargo ) do - local Cargo = Cargo -- Cargo.Cargo#CARGO - self:F( { IsLoaded = Cargo:IsLoaded(), IsDestroyed = Cargo:IsDestroyed(), Cargo:GetName(), AirplaneGroup: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. All cargo is inside the carrier and ready to be transported. -- @param #AI_CARGO_AIRPLANE self @@ -521,61 +401,6 @@ function AI_CARGO_AIRPLANE:onafterUnload( Airplane, From, Event, To, DeployZone 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, AirplaneUnit, DeployZone ) - - self:E( { "Unboard", Cargo } ) - - if Airplane and Airplane:IsAlive() then - if not Cargo:IsUnLoaded() then - self:__Unboard( 10, Cargo, AirplaneUnit, DeployZone ) - return - end - end - - self:Unloaded( Cargo, AirplaneUnit, DeployZone ) - -end - ---- On after Unloaded event. Cargo has been unloaded, i.e. the unboarding process is finished. --- @param #AI_CARGO_AIRPLANE self --- @param Wrapper.Group#GROUP Airplane Cargo transport plane. --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. --- @param Cargo.Cargo#CARGO Cargo -function AI_CARGO_AIRPLANE:onafterUnloaded( Airplane, From, Event, To, Cargo, AirplaneUnit, DeployZone ) - - local AllUnloaded = true - - if AirplaneUnit and AirplaneUnit:IsAlive() then - for _, AirplaneUnit in pairs( AirplaneUnit:GetUnits() ) do - local IsEmpty = AirplaneUnit:IsCargoEmpty() - self:I({ IsEmpty = IsEmpty }) - if not IsEmpty then - AllUnloaded = false - break - end - end - - if AllUnloaded == true then - if DeployZone then - self.Airplane_Cargo = {} - end - self.Airplane = AirplaneUnit - end - end - - if AllUnloaded == true then - self:Deployed( DeployZone ) - end - -end --- On after Deployed event. diff --git a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua index 62cdbf43a..b05c75dfe 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua @@ -21,7 +21,6 @@ AI_CARGO_HELICOPTER = { ClassName = "AI_CARGO_HELICOPTER", Coordinate = nil, -- Core.Point#COORDINATE, - Helicopter_Cargo = {}, } AI_CARGO_QUEUE = {} @@ -33,7 +32,7 @@ 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 @@ -379,115 +378,6 @@ 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. --- @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:onbeforeLoad( Helicopter, From, Event, To, PickupZone ) - - local Boarding = false - - local LoadInterval = 10 - local LoadDelay = 10 - - if Helicopter and Helicopter:IsAlive() then - - self.BoardingCount = 0 - - 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( LoadDelay, HelicopterUnit, 25 ) - LoadDelay = LoadDelay + LoadInterval - self:__Board( LoadDelay, Cargo, HelicopterUnit, PickupZone ) - self.Helicopter_Cargo[HelicopterUnit] = Cargo - Boarding = true - CargoBayFreeWeight = CargoBayFreeWeight - CargoWeight - 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 --- @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:onafterBoard( Helicopter, From, Event, To, Cargo, HelicopterUnit, PickupZone ) - 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, PickupZone ) - return - end - end - - self:__Loaded( 10, Cargo, HelicopterUnit, PickupZone ) -- Will only be executed when no more cargo is boarded. - -end - - ---- On After 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. --- @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:onafterLoaded( Helicopter, From, Event, To, Cargo, HelicopterUnit, PickupZone ) - 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 - - if Loaded then - self:PickedUp( PickupZone ) - end - -end - - - --- On after PickedUp event, raised when all cargo has been loaded into the CarrierGroup. -- @param #AI_CARGO_HELICOPTER self @@ -507,95 +397,6 @@ function AI_CARGO_HELICOPTER:onafterPickedUp( Helicopter, From, Event, To, Picku 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, DeployZone ) - - local UnboardInterval = 10 - local UnboardDelay = 10 - - 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( UnboardDelay ) - UnboardDelay = UnboardDelay + UnboardInterval - Cargo:SetDeployed( true ) - self:__Unboard( UnboardDelay, Cargo, HelicopterUnit, DeployZone ) - 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, HelicopterUnit, DeployZone ) - - if Helicopter and Helicopter:IsAlive() then - if not Cargo:IsUnLoaded() then - self:__Unboard( 10, Cargo, HelicopterUnit, DeployZone ) - return - end - end - - self:Unloaded( Cargo, HelicopterUnit, DeployZone ) - -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. --- @return #boolean True if all cargo has been unloaded. -function AI_CARGO_HELICOPTER:onafterUnloaded( Helicopter, From, Event, To, Cargo, HelicopterUnit, DeployZone ) - self:F( { Helicopter, From, Event, To, Cargo:GetName(), HelicopterUnit:GetName(), DeployZone = DeployZone } ) - - 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 DeployZone then - self.Helicopter_Cargo = {} - end - self.Helicopter = Helicopter - end - end - - if AllUnloaded == true then - self:Deployed( DeployZone ) - end - -end - --- On after Deployed event. -- @param #AI_CARGO_HELICOPTER self diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index a6f83c5c0..ef91a1cff 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -1937,7 +1937,7 @@ do -- Route methods -- @param #CONTROLLABLE self -- @return #CONTROLLABLE function CONTROLLABLE:RouteStop() - self:F("RouteStop") + self:F(self:GetName() .. "RouteStop") local CommandStop = self:CommandStopRoute( true ) self:SetCommand( CommandStop ) @@ -1948,7 +1948,7 @@ do -- Route methods -- @param #CONTROLLABLE self -- @return #CONTROLLABLE function CONTROLLABLE:RouteResume() - self:F("RouteResume") + self:F( self:GetName() .. " RouteResume") local CommandResume = self:CommandStopRoute( false ) self:SetCommand( CommandResume ) From 415b74019691fa7ee265fdf140634c669f76d892 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 5 Sep 2018 20:11:41 +0200 Subject: [PATCH 04/11] Workable solution? --- Moose Development/Moose/AI/AI_Cargo.lua | 66 ++++--------------- Moose Development/Moose/AI/AI_Cargo_APC.lua | 9 +-- .../Moose/AI/AI_Cargo_Airplane.lua | 33 ++++++++-- .../Moose/AI/AI_Cargo_Dispatcher.lua | 13 ++-- .../Moose/AI/AI_Cargo_Dispatcher_APC.lua | 2 +- .../AI/AI_Cargo_Dispatcher_Helicopter.lua | 2 +- .../Moose/AI/AI_Cargo_Helicopter.lua | 33 ++++++++-- 7 files changed, 83 insertions(+), 75 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo.lua b/Moose Development/Moose/AI/AI_Cargo.lua index bd379f299..81be2f8e3 100644 --- a/Moose Development/Moose/AI/AI_Cargo.lua +++ b/Moose Development/Moose/AI/AI_Cargo.lua @@ -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. -- -- === -- @@ -7,69 +7,25 @@ -- === -- -- @module AI.AI_Cargo --- @image AI_Cargo_Dispatching.JPG +-- @image Cargo.JPG --- @type AI_CARGO -- @extends Core.Fsm#FSM_CONTROLLABLE ---- Brings a dynamic cargo handling capability for AI groups. +--- Base class for the dynamic cargo handling capability for AI groups. -- --- Armoured Personnel Carriers (Carrier), Trucks, Jeeps and other ground based carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation. --- The AI\_CARGO\Carrier module uses the @{Cargo} capabilities within the MOOSE framework. --- CARGO derived objects must be declared within the mission to make the AI\_CARGO\Carrier object recognize the cargo. +-- Carriers can be mobilized to intelligently transport infantry and other cargo within the simulation. +-- The AI_CARGO module uses the @{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} module for more information. -- --- ## Cargo loading. --- --- The module will load automatically cargo when the Carriers are within boarding or loading range. --- The boarding or loading range is specified when the cargo is created in the simulation, and therefore, this range depends on the type of cargo --- and the specified boarding range. --- --- ## Enemies nearby. --- --- When the Carriers are approaching enemy units, something special is happening. --- The Carriers will stop moving, and the loaded infantry will unboard and follow the Carriers and will help to defend the group. --- The carrier will hold the route once the unboarded infantry is further than 50 meters from the Carriers, --- to ensure that the Carriers are not too far away from the following running infantry. --- Once all enemies are cleared, the infantry will board again automatically into the Carriers. Once boarded, the Carriers will follow its pre-defined route. --- --- A combat range needs to be specified in meters at the @{#AI_CARGO.New}() method. --- This combat range will trigger the unboarding of troops when enemies are within the combat range around the Carriers. --- During my tests, I've noticed that there is a balance between ensuring that the infantry is within sufficient hit range (effectiveness) versus --- vulnerability of the infantry. It all depends on the kind of enemies that are expected to be encountered. --- A combat range of 350 meters to 500 meters has been proven to be the most effective and efficient. --- --- ## Infantry health. --- --- When infantry is unboarded from the Carriers, 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 and following the Carriers, 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 ... --- --- ## Control the Carriers on the map. --- --- It is possible also as a human ground commander to influence the path of the Carriers, by pointing a new path using the DCS user interface on the map. --- In this case, the Carriers will change the direction towards its new indicated route. However, there is a catch! --- Once the Carriers are near the enemy, and infantry is unboarded, the Carriers won't be able to hold the route until the infantry could catch up. --- The Carriers will simply drive on and won't stop! This is a limitation in ED that prevents user actions being controlled by the scripting engine. --- No workaround is possible on this. --- --- ## Cargo deployment. --- --- Using the @{#AI_CARGO.Deploy}() method, you are able to direct the Carriers towards a point on the battlefield to unboard/unload the cargo at the specific coordinate. --- The Carriers will follow nearby roads as much as possible, to ensure fast and clean cargo transportation between the objects and villages in the simulation environment. --- --- ## Cargo pickup. --- --- Using the @{#AI_CARGO.Pickup}() method, you are able to direct the Carriers towards a point on the battlefield to board/load the cargo at the specific coordinate. --- The Carriers will follow nearby roads as much as possible, to ensure fast and clean cargo transportation between the objects and villages in the simulation environment. --- --- +-- 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", diff --git a/Moose Development/Moose/AI/AI_Cargo_APC.lua b/Moose Development/Moose/AI/AI_Cargo_APC.lua index f991346a9..9404c448a 100644 --- a/Moose Development/Moose/AI/AI_Cargo_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_APC.lua @@ -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. -- -- === -- @@ -13,11 +13,12 @@ -- @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. +-- +-- The AI_CARGO_APC class uses the @{Cargo} capabilities within the MOOSE framework. +-- @{Cargo} must be declared within the mission to make the AI_CARGO_APC object recognize the cargo. -- Please consult the @{Cargo} module for more information. -- -- ## Cargo loading. diff --git a/Moose Development/Moose/AI/AI_Cargo_Airplane.lua b/Moose Development/Moose/AI/AI_Cargo_Airplane.lua index 882ea6d36..d19de0cb1 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Airplane.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Airplane.lua @@ -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 ---- 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} capabilities within the MOOSE framework. +-- @{Cargo} must be declared within the mission to make AI_CARGO_AIRPLANE recognize the cargo. +-- Please consult the @{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 = { @@ -30,8 +57,6 @@ function AI_CARGO_AIRPLANE:New( Airplane, CargoSet ) local self = BASE:Inherit( self, AI_CARGO:New( Airplane, CargoSet ) ) -- #AI_CARGO_AIRPLANE - self.CargoSet = CargoSet -- Cargo.CargoGroup#CARGO_GROUP - self:AddTransition( "*", "Landed", "*" ) self:AddTransition( "*", "Home" , "*" ) diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua index 1ffc9b9b9..3ee909975 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua @@ -16,25 +16,25 @@ --- 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 +-- 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. +-- @{Cargo} must be declared within the mission to make the AI_CARGO_DISPATCHER object recognize the cargo. -- Please consult the @{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) -- --- ## 2.1) AI\_CARGO\_DISPATCHER States +-- ## 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. @@ -47,6 +47,7 @@ -- * **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) Enhance your mission scripts with **Tailored** Event Handling! diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua index 0f63f2f94..78fe76f31 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua @@ -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:** -- diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua index 61705d84d..5c64ef549 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua @@ -1,4 +1,4 @@ ---- **AI** -- Models the intelligent transportation of infantry and other cargo using Helicopters. +--- **AI** -- (2.4) - Models the intelligent transportation of infantry and other cargo using Helicopters. -- -- **Features:** -- diff --git a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua index b05c75dfe..7e32c9495 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua @@ -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} capabilities within the MOOSE framework. +-- @{Cargo} must be declared within the mission to make the AI_CARGO_HELICOPTER object recognize the cargo. +-- Please consult the @{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 ... +-- -- -- === -- @@ -34,8 +61,6 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet ) 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" ) From ab19c696c3c3bedc378337716a5717803dc20514 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 5 Sep 2018 20:55:56 +0200 Subject: [PATCH 05/11] Fixing an issue with cargo links. --- Moose Development/Moose/AI/AI_Cargo.lua | 4 ++-- Moose Development/Moose/AI/AI_Cargo_APC.lua | 6 +++--- Moose Development/Moose/AI/AI_Cargo_Airplane.lua | 6 +++--- Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua | 8 ++++---- Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua | 4 ++-- .../Moose/AI/AI_Cargo_Dispatcher_Airplane.lua | 2 +- .../Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua | 4 ++-- Moose Development/Moose/AI/AI_Cargo_Helicopter.lua | 6 +++--- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo.lua b/Moose Development/Moose/AI/AI_Cargo.lua index 81be2f8e3..8e145a8c4 100644 --- a/Moose Development/Moose/AI/AI_Cargo.lua +++ b/Moose Development/Moose/AI/AI_Cargo.lua @@ -16,9 +16,9 @@ --- 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} capabilities within the MOOSE framework. +-- 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} module for more information. +-- Please consult the @{Cargo.Cargo} module for more information. -- -- The derived classes from this module are: -- diff --git a/Moose Development/Moose/AI/AI_Cargo_APC.lua b/Moose Development/Moose/AI/AI_Cargo_APC.lua index 9404c448a..fb16616ea 100644 --- a/Moose Development/Moose/AI/AI_Cargo_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_APC.lua @@ -17,9 +17,9 @@ -- -- 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 class uses the @{Cargo} capabilities within the MOOSE framework. --- @{Cargo} 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. -- diff --git a/Moose Development/Moose/AI/AI_Cargo_Airplane.lua b/Moose Development/Moose/AI/AI_Cargo_Airplane.lua index d19de0cb1..0b4be9907 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Airplane.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Airplane.lua @@ -17,9 +17,9 @@ -- -- 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} capabilities within the MOOSE framework. --- @{Cargo} must be declared within the mission to make AI_CARGO_AIRPLANE recognize the cargo. --- Please consult the @{Cargo} module for more information. +-- 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. -- diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua index 3ee909975..ed7148e8a 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua @@ -16,10 +16,10 @@ --- 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} 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 -- diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua index 78fe76f31..020e6c15e 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua @@ -36,7 +36,7 @@ -- -- 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} capabilities within the MOOSE framework. +-- 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. -- @@ -98,7 +98,7 @@ AI_CARGO_DISPATCHER_APC = { --- Creates a new AI_CARGO_DISPATCHER_APC object. -- @param #AI_CARGO_DISPATCHER_APC self -- @param Core.Set#SET_GROUP APCSet The collection of APC @{Wrapper.Group}s. --- @param Core.Set#SET_CARGO CargoSet The collection of @{Cargo} derived objects. +-- @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. diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua index fc6bde8de..e094b3532 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua @@ -29,7 +29,7 @@ -- -- 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} capabilities within the MOOSE framework. +-- 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. -- diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua index 5c64ef549..8da835dff 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua @@ -32,7 +32,7 @@ -- -- 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} capabilities within the MOOSE framework. +-- 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. -- @@ -103,7 +103,7 @@ AI_CARGO_DISPATCHER_HELICOPTER = { --- Creates a new AI_CARGO_DISPATCHER_HELICOPTER object. -- @param #AI_CARGO_DISPATCHER_HELICOPTER self -- @param Core.Set#SET_GROUP HelicopterSet The collection of Helicopter @{Wrapper.Group}s. --- @param Core.Set#SET_CARGO CargoSet The collection of @{Cargo} derived objects. +-- @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 diff --git a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua index 7e32c9495..2c82fb1e3 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua @@ -17,9 +17,9 @@ -- -- Helicopter carriers can be mobilized to intelligently transport infantry and other cargo within the simulation. -- --- The AI_CARGO_HELICOPTER class uses the @{Cargo} capabilities within the MOOSE framework. --- @{Cargo} must be declared within the mission to make the AI_CARGO_HELICOPTER object recognize the cargo. --- Please consult the @{Cargo} module for more information. +-- 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. -- From ea60e4358499c8378cbce0c61750e026293ada04 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 5 Sep 2018 21:24:11 +0200 Subject: [PATCH 06/11] Documentation updates --- .../Moose/AI/AI_Cargo_Dispatcher.lua | 56 ++++++++++++++----- .../Moose/AI/AI_Cargo_Dispatcher_APC.lua | 2 +- .../Moose/AI/AI_Cargo_Dispatcher_Airplane.lua | 2 +- .../AI/AI_Cargo_Dispatcher_Helicopter.lua | 2 +- 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua index ed7148e8a..d8319f7cc 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua @@ -27,8 +27,35 @@ -- -- # 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. -- +-- 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. @@ -36,9 +63,10 @@ -- -- ## 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. @@ -319,7 +347,7 @@ -- * @{#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. @@ -372,19 +400,19 @@ function AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo ) self:AddTransition( "Monitoring", "Stop", "Idle" ) - self:AddTransition( "*", "Pickup", "*" ) - self:AddTransition( "*", "Load", "*" ) - self:AddTransition( "*", "Loading", "*" ) - self:AddTransition( "*", "Loaded", "*" ) - self:AddTransition( "*", "PickedUp", "*" ) + 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( "*", "Unload", "*" ) - self:AddTransition( "*", "Unloading", "*" ) - self:AddTransition( "*", "Unloaded", "*" ) - self:AddTransition( "*", "Deployed", "*" ) + 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( "Monitoring", "Home", "Monitoring" ) self.MonitorTimeInterval = 30 self.DeployRadiusInner = 200 diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua index 020e6c15e..fffaaf90f 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_APC.lua @@ -32,7 +32,7 @@ -- 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#AI_CARGO_DISPATCHER} !!!** +-- **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! -- diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua index e094b3532..1df08d56f 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua @@ -25,7 +25,7 @@ -- 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#AI_CARGO_DISPATCHER} !!!** +-- **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! -- diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua index 8da835dff..69beb31f4 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua @@ -28,7 +28,7 @@ -- 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#AI_CARGO_DISPATCHER} !!!** +-- **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! -- From c160ecbce53d705844ea5e5889706b1addbc7b94 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 5 Sep 2018 21:37:01 +0200 Subject: [PATCH 07/11] Cargo documentation optimization --- Moose Development/Moose/Cargo/CargoGroup.lua | 12 ++++-------- Moose Development/Moose/Cargo/CargoSlingload.lua | 5 +++++ Moose Development/Moose/Cargo/CargoUnit.lua | 5 ++++- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Moose Development/Moose/Cargo/CargoGroup.lua b/Moose Development/Moose/Cargo/CargoGroup.lua index ade21edd0..95ac1c266 100644 --- a/Moose Development/Moose/Cargo/CargoGroup.lua +++ b/Moose Development/Moose/Cargo/CargoGroup.lua @@ -1,10 +1,6 @@ --- **Cargo** -- Management of grouped cargo logistics, which are based on a @{Wrapper.Group} object. -- -- === --- --- ![Banner Image](..\Presentations\CARGO\Dia1.JPG) --- --- === -- -- ### [Demo Missions]() -- @@ -33,12 +29,12 @@ do -- CARGO_GROUP -- -- The above cargo classes are used by the AI\_CARGO\_ classes to allow AI groups to transport cargo: -- - -- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC#AI_CARGO_APC} class. - -- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter#AI_CARGO_HELICOPTER} class. - -- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Plane#AI_CARGO_PLANE} class. + -- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC} module. + -- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter} module. + -- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Airplane} module. -- * AI Ships is planned. -- - -- The above cargo classes are also used by the TASK\_CARGO\_ classes to allow human players to transport cargo as part of a tasking: + -- The above cargo classes are also used by the TASK_CARGO_ classes to allow human players to transport cargo as part of a tasking: -- -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players. -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players. diff --git a/Moose Development/Moose/Cargo/CargoSlingload.lua b/Moose Development/Moose/Cargo/CargoSlingload.lua index ff948d4e6..452bbe3e8 100644 --- a/Moose Development/Moose/Cargo/CargoSlingload.lua +++ b/Moose Development/Moose/Cargo/CargoSlingload.lua @@ -25,6 +25,11 @@ do -- CARGO_SLINGLOAD --- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier. -- + -- The above cargo classes are also used by the TASK_CARGO_ classes to allow human players to transport cargo as part of a tasking: + -- + -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players. + -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players. + -- -- === -- -- @field #CARGO_SLINGLOAD diff --git a/Moose Development/Moose/Cargo/CargoUnit.lua b/Moose Development/Moose/Cargo/CargoUnit.lua index 68e77ac61..18ff9743d 100644 --- a/Moose Development/Moose/Cargo/CargoUnit.lua +++ b/Moose Development/Moose/Cargo/CargoUnit.lua @@ -23,7 +23,10 @@ do -- CARGO_UNIT -- @extends Cargo.Cargo#CARGO_REPRESENTABLE --- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier. - -- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_UNIT objects to and from carriers. + -- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO_UNIT objects to and from carriers. + -- Note that ground forces behave in a group, and thus, act in formation, regardless if one unit is commanded to move. + -- + -- This class is used in CARGO_GROUP, and is not meant to be used by mission designers individually. -- -- === -- From e97badd092cf49c27da5e5e5650428ec1cd2c843 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 5 Sep 2018 21:57:50 +0200 Subject: [PATCH 08/11] Optimize --- Moose Development/Moose/Cargo/CargoCrate.lua | 12 ++++++++++++ Moose Development/Moose/Cargo/CargoGroup.lua | 4 +--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Moose Development/Moose/Cargo/CargoCrate.lua b/Moose Development/Moose/Cargo/CargoCrate.lua index 53011f56d..a1258d633 100644 --- a/Moose Development/Moose/Cargo/CargoCrate.lua +++ b/Moose Development/Moose/Cargo/CargoCrate.lua @@ -25,6 +25,18 @@ do -- CARGO_CRATE --- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier. -- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_CRATE objects to and from carriers. -- + -- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo: + -- + -- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC} module. + -- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter} module. + -- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Airplane} module. + -- * AI Ships is planned. + -- + -- The above cargo classes are also used by the TASK_CARGO_ classes to allow human players to transport cargo as part of a tasking: + -- + -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players. + -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players. + -- -- === -- -- @field #CARGO_CRATE diff --git a/Moose Development/Moose/Cargo/CargoGroup.lua b/Moose Development/Moose/Cargo/CargoGroup.lua index 95ac1c266..abcbb1e83 100644 --- a/Moose Development/Moose/Cargo/CargoGroup.lua +++ b/Moose Development/Moose/Cargo/CargoGroup.lua @@ -27,7 +27,7 @@ do -- CARGO_GROUP --- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator. -- The cargo can be Loaded, UnLoaded, Boarded, UnBoarded to and from Carriers. -- - -- The above cargo classes are used by the AI\_CARGO\_ classes to allow AI groups to transport cargo: + -- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo: -- -- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC} module. -- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter} module. @@ -39,8 +39,6 @@ do -- CARGO_GROUP -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players. -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players. -- - -- The - -- -- @field #CARGO_GROUP CARGO_GROUP -- CARGO_GROUP = { From 5c29f48a887792d79070839584580297baa95bc4 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Thu, 6 Sep 2018 18:36:31 +0200 Subject: [PATCH 09/11] Home event handler implementation for APCs and Helicopters. airplanes is to be further investigated. --- Moose Development/Moose/AI/AI_Cargo_APC.lua | 7 +- .../Moose/AI/AI_Cargo_Dispatcher.lua | 256 ++++++++++-------- .../Moose/AI/AI_Cargo_Helicopter.lua | 9 +- 3 files changed, 145 insertions(+), 127 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_APC.lua b/Moose Development/Moose/AI/AI_Cargo_APC.lua index fb16616ea..4df35bc4c 100644 --- a/Moose Development/Moose/AI/AI_Cargo_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_APC.lua @@ -261,6 +261,7 @@ function AI_CARGO_APC:onafterMonitor( APC, From, Event, To ) if self:Is( "Unloaded" ) then self:Follow() end + self:F( "I am here" .. self:GetCurrentState() ) if self:Is( "Following" ) then for Cargo, APCUnit in pairs( self.Carrier_Cargo ) do local Cargo = Cargo -- Cargo.Cargo#CARGO @@ -422,15 +423,15 @@ 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] diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua index d8319f7cc..6ae9d3de5 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua @@ -99,13 +99,13 @@ -- You can use this event handler to post messages to players, or provide status updates etc. -- -- --- --- Pickup Handler OnAfter for CLASS. +-- --- 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 fired. --- -- @param #string Event A string that contains the "*event name*" when the event was fired. --- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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. @@ -123,13 +123,13 @@ -- You can use this event handler to post messages to players, or provide status updates etc. -- -- --- --- Load Handler OnAfter for CLASS. +-- --- 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 fired. --- -- @param #string Event A string that contains the "*event name*" when the event was fired. --- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 ) @@ -145,14 +145,14 @@ -- You can use this event handler to post messages to players, or provide status updates etc. -- -- --- --- Loading Handler OnAfter for CLASS. +-- --- 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 fired repeatedly until all cargo (units) have been boarded into the carrier. +-- -- 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 fired. --- -- @param #string Event A string that contains the "*event name*" when the event was fired. --- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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. @@ -168,21 +168,21 @@ -- -- 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 fired multiple times for each different Cargo/CarrierUnit. +-- 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 Handler OnAfter for CLASS. +-- --- 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 fired multiple times for each different Cargo/CarrierUnit. +-- -- 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 fired. --- -- @param #string Event A string that contains the "*event name*" when the event was fired. --- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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. @@ -200,13 +200,13 @@ -- You can use this event handler to post messages to players, or provide status updates etc. -- -- --- --- PickedUp Handler OnAfter for CLASS. +-- --- 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 fired. --- -- @param #string Event A string that contains the "*event name*" when the event was fired. --- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 ) @@ -222,13 +222,13 @@ -- You can use this event handler to post messages to players, or provide status updates etc. -- -- --- --- Deploy Handler OnAfter for CLASS. +-- --- 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 fired. --- -- @param #string Event A string that contains the "*event name*" when the event was fired. --- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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. @@ -246,13 +246,13 @@ -- You can use this event handler to post messages to players, or provide status updates etc. -- -- --- --- Unload Handler OnAfter for CLASS. +-- --- 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 fired. --- -- @param #string Event A string that contains the "*event name*" when the event was fired. --- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 ) @@ -265,14 +265,14 @@ -- ## 3.8) Tailor the **Unloading** event -- -- --- --- UnLoading Handler OnAfter for CLASS. +-- --- 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 fired repeatedly until all cargo (units) have been unboarded from the CarrierUnit. +-- -- 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 fired. --- -- @param #string Event A string that contains the "*event name*" when the event was fired. --- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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. @@ -290,15 +290,15 @@ -- 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 Handler OnAfter for CLASS. +-- --- 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 fired multiple times for each different Cargo/CarrierUnit. +-- -- 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 fired. --- -- @param #string Event A string that contains the "*event name*" when the event was fired. --- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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. @@ -316,14 +316,13 @@ -- You can use this event handler to post messages to players, or provide status updates etc. -- -- --- --- Deployed Handler OnAfter for AI_CARGO_DISPATCHER. +-- --- 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. --- -- @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 fired. --- -- @param #string Event A string that contains the "*event name*" when the event was fired. --- -- @param #string To A string that contains the "*to state name*" when the event was fired. +-- -- @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 ) @@ -331,7 +330,30 @@ -- -- 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. -- @@ -668,14 +690,14 @@ function AI_CARGO_DISPATCHER:onafterMonitor() self.AI_Cargo[Carrier] = self:AICargo( Carrier, self.SetCargo, self.CombatRadius ) AI_Cargo = self.AI_Cargo[Carrier] - --- Pickup Handler OnAfter for AI_CARGO_DISPATCHER. + --- 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 fired. - -- @param #string Event A string that contains the "*event name*" when the event was fired. - -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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. @@ -684,14 +706,14 @@ function AI_CARGO_DISPATCHER:onafterMonitor() self:Pickup( CarrierGroup, Coordinate, Speed, PickupZone ) end - --- Load Handler OnAfter for AI_CARGO_DISPATCHER. + --- 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 fired. - -- @param #string Event A string that contains the "*event name*" when the event was fired. - -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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. @@ -699,15 +721,15 @@ function AI_CARGO_DISPATCHER:onafterMonitor() self:Load( CarrierGroup, PickupZone ) end - --- Loading Handler OnAfter for AI_CARGO_DISPATCHER. + --- 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 fired repeatedly until all cargo (units) have been boarded into the carrier. + -- 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 fired. - -- @param #string Event A string that contains the "*event name*" when the event was fired. - -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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. @@ -717,16 +739,16 @@ function AI_CARGO_DISPATCHER:onafterMonitor() self:Loading( CarrierGroup, Cargo, CarrierUnit, PickupZone ) end - --- Loaded Handler OnAfter for AI_CARGO_DISPATCHER. + --- 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 fired multiple times for each different Cargo/CarrierUnit. + -- 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 fired. - -- @param #string Event A string that contains the "*event name*" when the event was fired. - -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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. @@ -736,14 +758,14 @@ function AI_CARGO_DISPATCHER:onafterMonitor() self:Loaded( CarrierGroup, Cargo, CarrierUnit, PickupZone ) end - --- PickedUp Handler OnAfter for AI_CARGO_DISPATCHER. + --- 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 fired. - -- @param #string Event A string that contains the "*event name*" when the event was fired. - -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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. @@ -752,14 +774,14 @@ function AI_CARGO_DISPATCHER:onafterMonitor() end - --- Deploy Handler OnAfter for AI_CARGO_DISPATCHER. + --- 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 fired. - -- @param #string Event A string that contains the "*event name*" when the event was fired. - -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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. @@ -770,14 +792,14 @@ function AI_CARGO_DISPATCHER:onafterMonitor() end - --- Unload Handler OnAfter for AI_CARGO_DISPATCHER. + --- 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 fired. - -- @param #string Event A string that contains the "*event name*" when the event was fired. - -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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. @@ -785,15 +807,15 @@ function AI_CARGO_DISPATCHER:onafterMonitor() self:Unloading( Carrier, Cargo, CarrierUnit, DeployZone ) end - --- UnLoading Handler OnAfter for AI_CARGO_DISPATCHER. + --- 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 fired repeatedly until all cargo (units) have been unboarded from the CarrierUnit. + -- 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 fired. - -- @param #string Event A string that contains the "*event name*" when the event was fired. - -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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. @@ -804,16 +826,16 @@ function AI_CARGO_DISPATCHER:onafterMonitor() end - --- Unloaded Handler OnAfter for AI_CARGO_DISPATCHER. + --- 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 fired multiple times for each different Cargo/CarrierUnit. + -- 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 fired. - -- @param #string Event A string that contains the "*event name*" when the event was fired. - -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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. @@ -823,20 +845,38 @@ function AI_CARGO_DISPATCHER:onafterMonitor() self:Unloaded( Carrier, Cargo, CarrierUnit, DeployZone ) end - --- Deployed Handler OnAfter for AI_CARGO_DISPATCHER. + --- 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 fired. - -- @param #string Event A string that contains the "*event name*" when the event was fired. - -- @param #string To A string that contains the "*to state name*" when the event was fired. + -- @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 ... @@ -900,7 +940,7 @@ function AI_CARGO_DISPATCHER:onafterMonitor() if self.HomeZone then if not self.CarrierHome[Carrier] then self.CarrierHome[Carrier] = true - AI_Cargo:__Home( 60, self.HomeZone:GetRandomPointVec2() ) + AI_Cargo:__Home( 60, self.HomeZone:GetRandomPointVec2(), math.random( self.PickupMinSpeed, self.PickupMaxSpeed ), self.HomeZone ) end end end @@ -910,7 +950,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 @@ -918,7 +958,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 @@ -938,7 +978,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 @@ -946,7 +986,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 @@ -963,30 +1003,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 diff --git a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua index 2c82fb1e3..11d32053b 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua @@ -597,7 +597,8 @@ 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_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinate, Speed ) +-- @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 @@ -609,7 +610,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat Coordinate.y = math.random( 50, 200 ) - local _speed=Speed or Helicopter:GetSpeedMax()*0.5 + Speed = Speed or Helicopter:GetSpeedMax()*0.5 --- Create a route point of type air. local CoordinateFrom = Helicopter:GetCoordinate() @@ -617,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 @@ -628,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 ) From 5bd6f4901f1fd796bc8fdfb9d3fa067b9a3b30f0 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Thu, 6 Sep 2018 19:23:13 +0200 Subject: [PATCH 10/11] Fixed issues with pickup zones. --- Moose Development/Moose/AI/AI_Cargo_APC.lua | 8 ++++---- Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_APC.lua b/Moose Development/Moose/AI/AI_Cargo_APC.lua index 4df35bc4c..8b2bd9eee 100644 --- a/Moose Development/Moose/AI/AI_Cargo_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_APC.lua @@ -319,12 +319,12 @@ end --- @param #AI_CARGO_APC -- @param Wrapper.Group#GROUP APC -function AI_CARGO_APC._Pickup( APC, self, PickupZone ) +function AI_CARGO_APC._Pickup( APC, self, Coordinate, Speed, PickupZone ) APC:F( { "AI_CARGO_APC._Pickup:", APC:GetName() } ) if APC:IsAlive() then - self:Load( PickupZone) + self:Load( PickupZone ) self.Relocating = false self.Transporting = true end @@ -364,7 +364,7 @@ function AI_CARGO_APC:onafterPickup( APC, From, Event, To, Coordinate, Speed, Pi local Waypoints = APC:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true ) - local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Pickup", self, PickupZone ) + local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Pickup", self, Coordinate, Speed, PickupZone ) self:F({Waypoints = Waypoints}) local Waypoint = Waypoints[#Waypoints] @@ -372,7 +372,7 @@ function AI_CARGO_APC:onafterPickup( APC, From, Event, To, Coordinate, Speed, Pi 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, PickupZone ) + AI_CARGO_APC._Pickup( APC, self, Coordinate, Speed, PickupZone ) end self.Relocating = true diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua index 6ae9d3de5..58ed1ce92 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua @@ -900,7 +900,7 @@ function AI_CARGO_DISPATCHER:onafterMonitor() if not self.PickupZoneSet or PickupZone then for CarrierPickup, Coordinate in pairs( self.PickupCargo ) do if CarrierPickup:IsAlive() == true then - if CargoCoordinate:Get2DDistance( Coordinate ) <= 25 then + if CargoCoordinate:Get2DDistance( Coordinate ) <= 100 then CoordinateFree = false break end From 703dac8251b3087514d8c1eae9e2288a221e43bc Mon Sep 17 00:00:00 2001 From: FlightControl Date: Thu, 6 Sep 2018 20:31:33 +0200 Subject: [PATCH 11/11] Optimization solving the overloading problem with Loaded event for cargo deployment. --- Moose Development/Moose/AI/AI_Cargo.lua | 2 +- Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo.lua b/Moose Development/Moose/AI/AI_Cargo.lua index 8e145a8c4..885d717de 100644 --- a/Moose Development/Moose/AI/AI_Cargo.lua +++ b/Moose Development/Moose/AI/AI_Cargo.lua @@ -414,7 +414,7 @@ function AI_CARGO:onafterUnloaded( Carrier, From, Event, To, Cargo, CarrierUnit, end if AllUnloaded == true then - self:Deployed( DeployZone ) + self:__Deployed( 5, DeployZone ) end end diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua index 58ed1ce92..eb448955f 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua @@ -428,6 +428,8 @@ function AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo ) self:AddTransition( "Monitoring", "Loaded", "Monitoring" ) self:AddTransition( "Monitoring", "PickedUp", "Monitoring" ) + self:AddTransition( "Monitoring", "Transport", "Monitoring" ) + self:AddTransition( "Monitoring", "Deploy", "Monitoring" ) self:AddTransition( "Monitoring", "Unload", "Monitoring" ) self:AddTransition( "Monitoring", "Unloading", "Monitoring" ) @@ -771,6 +773,7 @@ function AI_CARGO_DISPATCHER:onafterMonitor() function AI_Cargo.OnAfterPickedUp( AI_Cargo, CarrierGroup, From, Event, To, PickupZone ) self:PickedUp( CarrierGroup, PickupZone ) + self:Transport( CarrierGroup ) end @@ -1011,7 +1014,7 @@ 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.DeployZoneSet then if self.AI_Cargo[Carrier]:IsTransporting() == true then