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 63f9203d1..abcbb1e83 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]() -- @@ -31,20 +27,18 @@ 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#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. -- - -- The - -- -- @field #CARGO_GROUP CARGO_GROUP -- CARGO_GROUP = { @@ -333,7 +327,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 +349,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/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 621a9a3a9..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. -- -- === -- @@ -285,15 +288,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 410c17c82..3984450c4 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -4790,7 +4790,7 @@ function SET_ZONE:AddZone(Zone) 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 #SET_ZONE self @@ -4805,6 +4805,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. @@ -5015,3 +5027,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 1adc3f820..a7a7f7a4f 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -1592,4 +1592,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 diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index ede2cb86c..97529a6fa 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -1932,7 +1932,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 ) @@ -1943,7 +1943,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 ) 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