diff --git a/Moose Development/Moose/AI/AI_Cargo_Ship.lua b/Moose Development/Moose/AI/AI_Cargo_Ship.lua index 5b7a4c9b4..7f3f6f5aa 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Ship.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Ship.lua @@ -40,7 +40,7 @@ function AI_CARGO_SHIP:SetCarrier( CargoCarrier ) self:F({AICargoTroops=AICargoTroops}) if AICargoTroops then self:F({}) - if not AICargoTroopsIs( "Loaded" ) then + if not AICargoTroops:Is( "Loaded" ) then -- Better hope they can swim! AICargoTroops:Destroyed() end @@ -92,6 +92,7 @@ function AI_CARGO_SHIP:SetCombatRadius( CombatRadius ) return self end + --- Follow Infantry to the Carrier -- @param #AI_CARGO_SHIP self -- @param #AI_CARGO_SHIP Me @@ -99,6 +100,7 @@ end -- @param Cargo.CargoGroup#CARGO_GROUP Cargo -- @return #AI_CARGO_SHIP function AI_CARGO_SHIP:FollowToCarrier( Me, ShipUnit, CargoGroup ) + BASE:T("DEBUGGING*** AI_CARGO_SHIP:FollowToCarrier") local InfantryGroup = CargoGroup:GetGroup() self:F( { self=self:GetClassNameAndID(), InfantryGroup = InfantryGroup:GetName() } ) @@ -107,35 +109,35 @@ function AI_CARGO_SHIP:FollowToCarrier( Me, ShipUnit, CargoGroup ) -- Check if the Cargo is near the CargoCarrier if InfantryGroup:IsPartlyInZone( ZONE_UNIT:New( "Radius", ShipUnit, 1000 ) ) then - -- Cargo does not need to navigate to Carrier - Me:Guard() + -- Cargo does not need to navigate to Carrier + Me:Guard() else - self:F( { InfantryGroup = InfantryGroup:GetName() } ) - if InfantryGroup:IsAlive() then - self:F( { InfantryGroup = InfantryGroup:GetName() } ) - local Waypoints = {} + if InfantryGroup:IsAlive() then - -- Calculate new route - local FromCoord = InfantryGroup:GetCoordinate() - local FromGround = FromCoord:WaypointGround( 10, "Diamond" ) - self:F({FromGround=FromGround}) - table.insert( Waypoints, FromGround ) + self:F( { InfantryGroup = InfantryGroup:GetName() } ) + local Waypoints = {} - local ToCoord = ShipUnit:GetCoordinate():GetRandomCoordinateInRadius( 10, 5 ) - local ToGround = ToCoord:WaypointGround( 10, "Diamond" ) - self:F({ToGround=ToGround}) - table.insert( Waypoints, ToGround ) + -- Calculate new route + local FromCoord = InfantryGroup:GetCoordinate() + local FromGround = FromCoord:WaypointGround( 10, "Diamond" ) + self:F({FromGround=FromGround}) + table.insert( Waypoints, FromGround ) - local TaskRoute = InfantryGroup:TaskFunction( "AI_CARGO_SHIP.FollowToCarrier", Me, ShipUnit, CargoGroup ) + local ToCoord = ShipUnit:GetCoordinate():GetRandomCoordinateInRadius( 10, 5 ) + local ToGround = ToCoord:WaypointGround( 10, "Diamond" ) + self:F({ToGround=ToGround}) + table.insert( Waypoints, ToGround ) - self:F({Waypoints=Waypoints}) - local Waypoint = Waypoints[#Waypoints] - InfantryGroup:SetTaskWaypoint( Waypoint, TaskRoute ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone + local TaskRoute = InfantryGroup:TaskFunction( "AI_CARGO_SHIP.FollowToCarrier", Me, ShipUnit, CargoGroup ) - InfantryGroup:Route( Waypoints, 1 ) -- Move after a random number of seconds to the Route. See Route method for details - end + 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 number of seconds to the Route. See Route method for details + end end end end @@ -146,76 +148,57 @@ function AI_CARGO_SHIP:onafterMonitor( Ship, From, Event, To ) if self.CombatRadius > 0 then if Ship and Ship:IsAlive() then - if self.CarrierCoordinate then - if self:IsTransporting() == true then - local Coordinate = Ship:GetCoordinate() - if self:Is( "Unloaded" ) or self:Is( "Loaded" ) then - self.Zone:Scan( { Object.Category.UNIT } ) - if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then - if self:Is( "Unloaded" ) then - -- There are no enemies within combat radius. Reload the CargoCarrier. - self:Reload() - end - else - if self:Is( "Loaded" ) then - -- There are enemies within combat radius. Unload the CargoCarrier. - self:__Unload( 1, nil, true ) -- The 2nd parameter is true, which means that the unload is for defending the carrier, not to deploy! - else - if self:Is( "Unloaded" ) then - --self:Follow() - end - self:F( "I am here" .. self:GetCurrentState() ) - if self:Is( "Following" ) then - for Cargo, ShipUnit in pairs( self.Carrier_Cargo ) do - local Cargo = Cargo -- Cargo.Cargo#CARGO - local ShipUnit = ShipUnit -- Wrapper.Unit#UNIT - if Cargo:IsAlive() then - if not Cargo:IsNear( ShipUnit, 40 ) then - ShipUnit:RouteStop() - self.CarrierStopped = true - else - if self.CarrierStopped then - if Cargo:IsNear( ShipUnit, 25 ) then - ShipUnit:RouteResume() - self.CarrierStopped = nil - end + if self.CarrierCoordinate then + if self:IsTransporting() == true then + local Coordinate = Ship:GetCoordinate() + if self:Is( "Unloaded" ) or self:Is( "Loaded" ) then + self.Zone:Scan( { Object.Category.UNIT } ) + if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then + if self:Is( "Unloaded" ) then + -- There are no enemies within combat radius. Reload the CargoCarrier. + self:Reload() + end + else + if self:Is( "Loaded" ) then + -- There are enemies within combat radius. Unload the CargoCarrier. + self:__Unload( 1, nil, true ) -- The 2nd parameter is true, which means that the unload is for defending the carrier, not to deploy! + else + if self:Is( "Unloaded" ) then + --self:Follow() + end + self:F( "I am here" .. self:GetCurrentState() ) + if self:Is( "Following" ) then + for Cargo, ShipUnit in pairs( self.Carrier_Cargo ) do + local Cargo = Cargo -- Cargo.Cargo#CARGO + local ShipUnit = ShipUnit -- Wrapper.Unit#UNIT + if Cargo:IsAlive() then + if not Cargo:IsNear( ShipUnit, 40 ) then + ShipUnit:RouteStop() + self.CarrierStopped = true + else + if self.CarrierStopped then + if Cargo:IsNear( ShipUnit, 25 ) then + ShipUnit:RouteResume() + self.CarrierStopped = nil + end + end + end + end + end + end + end end end - end - end end end - end - end - end - + self.CarrierCoordinate = Ship:GetCoordinate() end - self.CarrierCoordinate = Ship:GetCoordinate() - end - self:__Monitor( -5 ) end - end -function AI_CARGO_SHIP:onafterFollow( Ship, From, Event, To ) - self:F( { Ship, From, Event, To } ) - - self:F( "Follow" ) - if Ship and Ship:IsAlive() then - for Cargo, ShipUnit in pairs( self.Carrier_Cargo ) do - local Cargo = Cargo -- Cargo.Cargo#CARGO - if Cargo:IsUnLoaded() then - self:FollowToCarrier( self, ShipUnit, Cargo ) - ShipUnit:RouteResume() - end - end - end - -end function AI_CARGO_SHIP._Pickup( Ship, self, Coordinate, Speed, PickupZone ) - Ship:F( { "AI_CARGO_Ship._Pickup:", Ship:GetName() } ) if Ship:IsAlive() then @@ -233,6 +216,39 @@ function AI_CARGO_SHIP._Deploy( Ship, self, Coordinate, DeployZone ) end end +function AI_CARGO_SHIP:onafterPickup( Ship, From, Event, To, Coordinate, Speed, Height, PickupZone ) + + if Ship and Ship:IsAlive() then + AI_CARGO_SHIP._Pickup( Ship, self, Coordinate, Speed, PickupZone ) + self:GetParent( self, AI_CARGO_SHIP ).onafterPickup( self, Ship, From, Event, To, Coordinate, Speed, Height, PickupZone ) + end +end + +function AI_CARGO_SHIP:onafterPickedUp( Ship, From, Event, To, Coordinate, Speed, Height, PickupZone ) + + if Ship and Ship:IsAlive() then + Speed = Speed or Ship:GetSpeedMax()*0.8 + + local lane = self.ShippingLane + if lane then + local Waypoints = {} + + for i=1, #lane do + local coord = lane[i] + local Waypoint = coord:WaypointGround(_speed) + table.insert(Waypoints, Waypoint) + end + + local Waypoint = Waypoints[#Waypoints] + Ship:Route(Waypoints, 1) + + else + BASE:T("ERROR: No shipping lane defined for Naval Transport!") + end + end +end + + function AI_CARGO_SHIP:onafterHome( Ship, From, Event, To, Coordinate, Speed, Height, HomeZone ) if Ship and Ship:IsAlive() then @@ -251,15 +267,12 @@ function AI_CARGO_SHIP:onafterHome( Ship, From, Event, To, Coordinate, Speed, He table.insert(Waypoints, Waypoint) end - --local TaskFunction = self:_SimpleTaskFunction( "warehouse:_Arrived", Ship ) - local Waypoint = Waypoints[#Waypoints] - --Ship:SetTaskWaypoint( Waypoint, TaskFunction ) Ship:Route(Waypoints, 1) else - BASE:T("ERROR: No shipping lane defined for Naval Transport!") + BASE:T("ERROR: No shipping lane defined for Naval Transport!") end end end diff --git a/Moose Development/Moose/Functional/Warehouse.lua b/Moose Development/Moose/Functional/Warehouse.lua index 1a2fce39e..d61c33984 100644 --- a/Moose Development/Moose/Functional/Warehouse.lua +++ b/Moose Development/Moose/Functional/Warehouse.lua @@ -1569,6 +1569,7 @@ WAREHOUSE = { delivered = {}, defending = {}, portzone = nil, + harborzone = nil, shippinglanes = {}, offroadpaths = {}, autodefence = false, @@ -2709,6 +2710,18 @@ function WAREHOUSE:SetPortZone(zone) return self end +--- Add a Harbor Zone for this warehouse where naval cargo units will spawn and be received. +-- Both warehouses must have the harbor zone defined for units to properly spawn on both the +-- sending and receiving side. The harbor zone should be within 3km of the port zone used for +-- warehouse in order to facilitate the boarding process. +-- @param #WAREHOUSE self +-- @param Core.Zone#ZONE zone The zone defining the naval embarcation/debarcation point for cargo units +-- @return #WAREHOUSE self +function WAREHOUSE:SetHarborZone(zone) + self.harborzone=zone + return self +end + --- Add a shipping lane from this warehouse to another remote warehouse. -- Note that both warehouses must have a port zone defined before a shipping lane can be added! -- Shipping lane is taken from the waypoints of a (late activated) template group. So set up a group, e.g. a ship or a helicopter, and place its @@ -4344,7 +4357,6 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request) -- Spawn Ship in port zone spawngroup=self:_SpawnAssetGroundNaval(_alias, _assetitem, Request, self.portzone) - return elseif Request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then @@ -4473,8 +4485,7 @@ function WAREHOUSE:onafterRequestSpawned(From, Event, To, Request, CargoGroupSet elseif Request.transporttype==WAREHOUSE.TransportType.APC then --_boardradius=nil elseif Request.transporttype==WAREHOUSE.TransportType.SHIP then - BASE:T("Big 'ol board radius") - _boardradius=5000 + _boardradius=6000 end -- Empty cargo group set. @@ -4485,7 +4496,7 @@ function WAREHOUSE:onafterRequestSpawned(From, Event, To, Request, CargoGroupSet -- Find asset belonging to this group. local asset=self:FindAssetInDB(_group) - + BASE:T("DEBUGGING*** load radius: "..asset.loadradius) -- New cargo group object. local cargogroup=CARGO_GROUP:New(_group, _cargotype,_group:GetName(),_boardradius, asset.loadradius) @@ -4494,6 +4505,7 @@ function WAREHOUSE:onafterRequestSpawned(From, Event, To, Request, CargoGroupSet -- Add group to group set. CargoGroups:AddCargo(cargogroup) + end ------------------------ @@ -4543,6 +4555,7 @@ function WAREHOUSE:onafterRequestSpawned(From, Event, To, Request, CargoGroupSet -- Pickup and deploy zones. local PickupZoneSet = SET_ZONE:New():AddZone(self.portzone) + PickupZoneSet:AddZone(self.harborzone) local DeployZoneSet = SET_ZONE:New():AddZone(Request.warehouse.portzone) -- Get the shipping lane to use and pass it to the Dispatcher @@ -4561,17 +4574,43 @@ function WAREHOUSE:onafterRequestSpawned(From, Event, To, Request, CargoGroupSet -- Set pickup and deploy radii. -- The 20 m inner radius are to ensure that the helo does not land on the warehouse itself in the middle of the default spawn zone. - local pickupouter=200 - local pickupinner=0 - if self.spawnzone.Radius~=nil then - pickupouter=self.spawnzone.Radius + local pickupouter = 200 + local pickupinner = 0 + local deployouter = 200 + local deployinner = 0 + if Request.transporttype==WAREHOUSE.TransportType.SHIP then + pickupouter=1000 pickupinner=20 - end - local deployouter=200 - local deployinner=0 - if self.spawnzone.Radius~=nil then - deployouter=Request.warehouse.spawnzone.Radius - deployinner=20 + deployouter=1000 + deployinner=0 + --BASE:T("DEBUGGING*** Let's try to move these units") + --[[for _,_group in pairs(CargoGroupSet:GetSetObjects()) do + local group=GROUP:FindByName( _group:GetName() ) --Wrapper.Group#GROUP + + + --local _speed = group:GetSpeedMax()*0.7 + BASE:T("DEBUGGING*** Group ".._.." coordinate is "..CargoTransport:GetCoordinate()) + --local FromCoord = group:GetCoordinate() + local ToCoord = CargoTransport:GetCoordinate() + + local FromWP = FromCoord:WaypointGround() + local ToWP = ToCoord:WaypointGround( 15, "Vee" ) + + group:Route( { FromWP, ToWP }, 10 ) + end]]-- + else + pickupouter=200 + pickupinner=0 + if self.spawnzone.Radius~=nil then + pickupouter=self.spawnzone.Radius + pickupinner=20 + end + deployouter=200 + deployinner=0 + if self.spawnzone.Radius~=nil then + deployouter=Request.warehouse.spawnzone.Radius + deployinner=20 + end end CargoTransport:SetPickupRadius(pickupouter, pickupinner) CargoTransport:SetDeployRadius(deployouter, deployinner) @@ -4600,6 +4639,15 @@ function WAREHOUSE:onafterRequestSpawned(From, Event, To, Request, CargoGroupSet -- Dispatcher Event Functions -- -------------------------------- + --- Function called before carrier loads something + function CargoTransport:OnBeforeMonitor(From, Event, To, Carrier, Cargo, PickupZone) + -- Need to get the cargo over to the portzone + -- But what if the cargo can't move on it's own? + BASE:T("DEBUGGING*** CargoTransport:OnBeforeMonitor") + + end + + --- Function called after carrier picked up something. function CargoTransport:OnAfterPickedUp(From, Event, To, Carrier, PickupZone) @@ -4650,7 +4698,7 @@ function WAREHOUSE:onafterRequestSpawned(From, Event, To, Request, CargoGroupSet -- Get cargo group object. local group=Cargo:GetObject() --Wrapper.Group#GROUP - -- Get request. + -- Get request. local request=warehouse:_GetRequestOfGroup(group, warehouse.pending) -- Add cargo group to this carrier.