From cce90b1f46da60f844ef1e851c4825320ac141a7 Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Mon, 26 Mar 2018 06:52:24 +0200 Subject: [PATCH 01/10] New AI_CARGO_TROOPS class --- .../Moose/AI/AI_Cargo_Troops.lua | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 Moose Development/Moose/AI/AI_Cargo_Troops.lua diff --git a/Moose Development/Moose/AI/AI_Cargo_Troops.lua b/Moose Development/Moose/AI/AI_Cargo_Troops.lua new file mode 100644 index 000000000..373c6682a --- /dev/null +++ b/Moose Development/Moose/AI/AI_Cargo_Troops.lua @@ -0,0 +1,105 @@ +--- **AI** -- (R2.3) - Models the intelligent transportation of infantry (cargo). +-- +-- === +-- +-- ### Author: **FlightControl** +-- +-- === +-- +-- @module AI_Cargo_Troops + +--- @type AI_Cargo_Troops +-- @extends Core.Base#BASE + + +--- # AI\_CARGO\_TROOPS class, extends @{Core.Base@BASE} +-- +-- === +-- +-- @field #AI_CARGO_TROOPS +AI_CARGO_TROOPS = { + ClassName = "AI_CARGO_TROOPS", +} + +--- Creates a new AI_CARGO_TROOPS object +-- @param #AI_CARGO_TROOPS self +-- @return #AI_CARGO_TROOPS +function AI_CARGO_TROOPS:New( CargoCarrier, CargoGroup, CombatRadius ) + + local self = BASE:Inherit( self, FSM_CONTROLLABLE:New( ) ) -- #AI_CARGO_TROOPS + + self.CargoCarrier = CargoCarrier -- Wrapper.Unit#UNIT + self.CargoGroup = CargoGroup -- Core.Cargo#CARGO_GROUP + self.CombatRadius = CombatRadius + + self:SetControllable( self.CargoCarrier ) + + self:SetStartState( "UnLoaded" ) + + self:AddTransition( "*", "Load", "Boarding" ) + self:AddTransition( "Boarding", "Boarding", "Boarding" ) + self:AddTransition( "Boarding", "Loaded", "Loaded" ) + self:AddTransition( "Loaded", "Unload", "Unboarding" ) + self:AddTransition( "UnBoarding", "Unloaded", "Unloaded" ) + + self:AddTransition( "*", "Monitor", "*" ) + + self:__Monitor( 1 ) + self:__Load( 1 ) + + return self +end + + +--- @param #AI_CARGO_TROOPS self +-- @param Wrapper.Unit#UNIT CargoCarrier +function AI_CARGO_TROOPS:onafterMonitor( CargoCarrier, From, Event, To ) + self:F( { CargoCarrier, From, Event, To } ) + + if CargoCarrier and CargoCarrier:IsAlive() then + end + + self:__Monitor( 1 ) + +end + + +--- @param #AI_CARGO_TROOPS self +-- @param Wrapper.Unit#UNIT CargoCarrier +function AI_CARGO_TROOPS:onafterLoad( CargoCarrier, From, Event, To ) + self:F( { CargoCarrier, From, Event, To } ) + + if CargoCarrier and CargoCarrier:IsAlive() then + self.CargoGroup:__Board( 1, CargoCarrier, 100 ) + self:__Boarding( 1 ) + end + +end + +--- @param #AI_CARGO_TROOPS self +-- @param Wrapper.Unit#UNIT CargoCarrier +function AI_CARGO_TROOPS:onafterBoarding( CargoCarrier, From, Event, To ) + self:F( { CargoCarrier, From, Event, To } ) + + if CargoCarrier and CargoCarrier:IsAlive() then + if self.CargoGroup:IsBoarding() then + self:__Boarding( 1 ) + end + + if self.CargoGroup:IsLoaded() then + self:__Loaded( 1 ) + end + end + +end + +--- @param #AI_CARGO_TROOPS self +-- @param Wrapper.Unit#UNIT CargoCarrier +function AI_CARGO_TROOPS:onafterLoaded( CargoCarrier, From, Event, To ) + self:F( { CargoCarrier, From, Event, To } ) + + if CargoCarrier and CargoCarrier:IsAlive() then + end + +end + From e7518d69e66c8c1b24591e11b0621f000b7d87d1 Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Mon, 26 Mar 2018 07:39:55 +0200 Subject: [PATCH 02/10] Cargo Troops --- .../Moose/AI/AI_Cargo_Troops.lua | 25 +++++++++++++++-- Moose Development/Moose/Core/Point.lua | 28 +++++++++++++++++++ .../Moose/Wrapper/Controllable.lua | 22 +++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_Troops.lua b/Moose Development/Moose/AI/AI_Cargo_Troops.lua index 373c6682a..58374618f 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Troops.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Troops.lua @@ -8,8 +8,8 @@ -- -- @module AI_Cargo_Troops ---- @type AI_Cargo_Troops --- @extends Core.Base#BASE +--- @type AI_CARGO_TROOPS +-- @extends Core.Fsm#FSM_CONTROLLABLE --- # AI\_CARGO\_TROOPS class, extends @{Core.Base@BASE} @@ -19,6 +19,7 @@ -- @field #AI_CARGO_TROOPS AI_CARGO_TROOPS = { ClassName = "AI_CARGO_TROOPS", + Coordinate = nil -- Core.Point#COORDINATE, } --- Creates a new AI_CARGO_TROOPS object @@ -32,6 +33,9 @@ function AI_CARGO_TROOPS:New( CargoCarrier, CargoGroup, CombatRadius ) self.CargoGroup = CargoGroup -- Core.Cargo#CARGO_GROUP self.CombatRadius = CombatRadius + self.Zone = ZONE_UNIT:New( self.CargoCarrier:GetName() .. "-Zone", self.CargoCarrier, CombatRadius ) + self.Coalition = self.CargoCarrier:GetCoalition() + self:SetControllable( self.CargoCarrier ) self:SetStartState( "UnLoaded" ) @@ -57,6 +61,22 @@ function AI_CARGO_TROOPS:onafterMonitor( CargoCarrier, From, Event, To ) self:F( { CargoCarrier, From, Event, To } ) if CargoCarrier and CargoCarrier:IsAlive() then + if self.Coordinate then + local Coordinate = CargoCarrier:GetCoordinate() + if Coordinate:IsAtCoordinate2D( self.Coordinate, 2 ) then + self.Zone:Scan( { Object.Category.UNIT } ) + if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then + else + if not self:Is( "Unloaded" ) then + -- There are enemies within combat range. Unload the CargoCarrier. + self:__Unload( 1 ) + self.CargoCarrier:RouteStop() + end + end + end + else + self.Coordinate = CargoCarrier:GetCoordinate() + end end self:__Monitor( 1 ) @@ -99,6 +119,7 @@ function AI_CARGO_TROOPS:onafterLoaded( CargoCarrier, From, Event, To ) self:F( { CargoCarrier, From, Event, To } ) if CargoCarrier and CargoCarrier:IsAlive() then + CargoCarrier:RouteStop() end end diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index b5556abea..df0a3d21a 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -192,6 +192,20 @@ do -- COORDINATE return self end + --- COORDINATE constructor. + -- @param #COORDINATE self + -- @param #COORDINATE Coordinate. + -- @return #COORDINATE + function COORDINATE:NewFromCoordinate( Coordinate ) + + local self = BASE:Inherit( self, BASE:New() ) -- #COORDINATE + self.x = Coordinate.x + self.y = Coordinate.y + self.z = Coordinate.z + + return self + end + --- Create a new COORDINATE object from Vec2 coordinates. -- @param #COORDINATE self -- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 point. @@ -241,6 +255,20 @@ do -- COORDINATE return { x = self.x, y = self.z } end + + --- Returns if the 2 coordinates are at the same 2D position. + -- @param #COORDINATE self + -- @return #boolean true if at the same position. + function COORDINATE:IsAtCoordinate2D( Coordinate, Precision ) + + local x = Coordinate.x + local z = Coordinate.z + + return x - Precision <= self.x and x + Precision >= self.x and z - Precision <= self.z and z + Precision >= self.z + end + + + --TODO: check this to replace --- Calculate the distance from a reference @{DCSTypes#Vec2}. -- @param #COORDINATE self diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index fe3d1378d..01fe228e4 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -1908,6 +1908,28 @@ function CONTROLLABLE:Route( Route, DelaySeconds ) end +--- Stops the movement of the vehicle on the route. +-- @param #CONTROLLABLE self +-- @return #CONTROLLABLE +function CONTROLLABLE:RouteStop() + self:F2() + + local CommandStop = self:CommandStopRoute( true ) + self:SetCommand( CommandStop ) + +end + +--- Resumes the movement of the vehicle on the route. +-- @param #CONTROLLABLE self +-- @return #CONTROLLABLE +function CONTROLLABLE:RouteResume() + self:F2() + + local CommandResume = self:CommandStopRoute( false ) + self:SetCommand( CommandResume ) + +end + --- Make the GROUND Controllable to drive towards a specific point. -- @param #CONTROLLABLE self -- @param Core.Point#COORDINATE ToCoordinate A Coordinate to drive to. From b6fc46fdd01a66d4aba855db96eafd547fcc5af2 Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Mon, 26 Mar 2018 17:53:23 +0200 Subject: [PATCH 03/10] Cargo Troops --- .../Moose/AI/AI_Cargo_Troops.lua | 89 ++++++++++++++----- Moose Development/Moose/Core/Cargo.lua | 22 +++++ 2 files changed, 90 insertions(+), 21 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_Troops.lua b/Moose Development/Moose/AI/AI_Cargo_Troops.lua index 58374618f..7cb69ab0c 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Troops.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Troops.lua @@ -36,15 +36,16 @@ function AI_CARGO_TROOPS:New( CargoCarrier, CargoGroup, CombatRadius ) self.Zone = ZONE_UNIT:New( self.CargoCarrier:GetName() .. "-Zone", self.CargoCarrier, CombatRadius ) self.Coalition = self.CargoCarrier:GetCoalition() - self:SetControllable( self.CargoCarrier ) + self:SetControllable( CargoCarrier ) self:SetStartState( "UnLoaded" ) self:AddTransition( "*", "Load", "Boarding" ) - self:AddTransition( "Boarding", "Boarding", "Boarding" ) + self:AddTransition( "Boarding", "Board", "Boarding" ) self:AddTransition( "Boarding", "Loaded", "Loaded" ) self:AddTransition( "Loaded", "Unload", "Unboarding" ) - self:AddTransition( "UnBoarding", "Unloaded", "Unloaded" ) + self:AddTransition( "Unboarding", "Unboard", "Unboarding" ) + self:AddTransition( "Unboarding", "Unloaded", "Unloaded" ) self:AddTransition( "*", "Monitor", "*" ) @@ -63,17 +64,24 @@ function AI_CARGO_TROOPS:onafterMonitor( CargoCarrier, From, Event, To ) if CargoCarrier and CargoCarrier:IsAlive() then if self.Coordinate then local Coordinate = CargoCarrier:GetCoordinate() - if Coordinate:IsAtCoordinate2D( self.Coordinate, 2 ) then - self.Zone:Scan( { Object.Category.UNIT } ) - if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then - else - if not self:Is( "Unloaded" ) then - -- There are enemies within combat range. Unload the CargoCarrier. - self:__Unload( 1 ) - self.CargoCarrier:RouteStop() - end + self.Zone:Scan( { Object.Category.UNIT } ) + if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then +-- if self:Is( "Unloaded" ) then +-- -- There are no enemies within combat range. Load the CargoCarrier. +-- self:__Load( 1 ) +-- end + else + if self:Is( "Loaded" ) then + -- There are enemies within combat range. Unload the CargoCarrier. + self:__Unload( 1 ) end end + if self:Is( "Unloaded" ) then + if not Coordinate:IsAtCoordinate2D( self.Coordinate, 2 ) then + --self.CargoGroup:RouteTo( Coordinate, 30 ) + end + end + else self.Coordinate = CargoCarrier:GetCoordinate() end @@ -90,23 +98,23 @@ function AI_CARGO_TROOPS:onafterLoad( CargoCarrier, From, Event, To ) self:F( { CargoCarrier, From, Event, To } ) if CargoCarrier and CargoCarrier:IsAlive() then - self.CargoGroup:__Board( 1, CargoCarrier, 100 ) - self:__Boarding( 1 ) + CargoCarrier:RouteStop() + self:Board() + self.CargoGroup:Board( CargoCarrier, 100 ) end end --- @param #AI_CARGO_TROOPS self -- @param Wrapper.Unit#UNIT CargoCarrier -function AI_CARGO_TROOPS:onafterBoarding( CargoCarrier, From, Event, To ) +function AI_CARGO_TROOPS:onafterBoard( CargoCarrier, From, Event, To ) self:F( { CargoCarrier, From, Event, To } ) if CargoCarrier and CargoCarrier:IsAlive() then - if self.CargoGroup:IsBoarding() then - self:__Boarding( 1 ) - end - - if self.CargoGroup:IsLoaded() then + self:F({ IsLoaded = self.CargoGroup:IsLoaded() } ) + if not self.CargoGroup:IsLoaded() then + self:__Board( 1 ) + else self:__Loaded( 1 ) end end @@ -119,8 +127,47 @@ function AI_CARGO_TROOPS:onafterLoaded( CargoCarrier, From, Event, To ) self:F( { CargoCarrier, From, Event, To } ) if CargoCarrier and CargoCarrier:IsAlive() then - CargoCarrier:RouteStop() + CargoCarrier:RouteResume() end end + +--- @param #AI_CARGO_TROOPS self +-- @param Wrapper.Unit#UNIT CargoCarrier +function AI_CARGO_TROOPS:onafterUnload( CargoCarrier, From, Event, To ) + self:F( { CargoCarrier, From, Event, To } ) + + if CargoCarrier and CargoCarrier:IsAlive() then + CargoCarrier:RouteStop() + self.CargoGroup:UnBoard( ) + self:__Unboard( 1 ) + end + +end + +--- @param #AI_CARGO_TROOPS self +-- @param Wrapper.Unit#UNIT CargoCarrier +function AI_CARGO_TROOPS:onafterUnboard( CargoCarrier, From, Event, To ) + self:F( { CargoCarrier, From, Event, To } ) + + if CargoCarrier and CargoCarrier:IsAlive() then + if not self.CargoGroup:IsUnLoaded() then + self:__Unboard( 1 ) + else + self:Unloaded() + end + end + +end + +--- @param #AI_CARGO_TROOPS self +-- @param Wrapper.Unit#UNIT CargoCarrier +function AI_CARGO_TROOPS:onafterUnloaded( CargoCarrier, From, Event, To ) + self:F( { CargoCarrier, From, Event, To } ) + + if CargoCarrier and CargoCarrier:IsAlive() then + CargoCarrier:RouteResume() + end + +end diff --git a/Moose Development/Moose/Core/Cargo.lua b/Moose Development/Moose/Core/Cargo.lua index 991669931..66f9c04c8 100644 --- a/Moose Development/Moose/Core/Cargo.lua +++ b/Moose Development/Moose/Core/Cargo.lua @@ -1312,6 +1312,7 @@ function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, if not Boarded then self:__Boarding( 1, CargoCarrier, NearRadius, ... ) else + self:F("Group Cargo is loaded") self:__Load( 1, CargoCarrier, ... ) end else @@ -1458,6 +1459,27 @@ end end end + + --- Route Cargo to Coordinate and randomize locations. + -- @param #CARGO_GROUP self + -- @param Core.Point#COORDINATE Coordinate + function CARGO_GROUP:RouteTo( Coordinate ) + self:F( ) + + --local NearRadius = NearRadius or 25 + + if From == "UnLoaded" then + + -- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2 + self.CargoSet:ForEach( + function( Cargo, Coordinate ) + Cargo.CargoObject:RouteTo( Coordinate ) + end, Coordinate + ) + + end + + end end -- CARGO_GROUP From 727d64927b79ffd2eb06c10efc7f49abd484219d Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Tue, 27 Mar 2018 12:07:16 +0200 Subject: [PATCH 04/10] First working prototype of AI_CARGO_TROOPS. --- .../Moose/AI/AI_Cargo_Troops.lua | 98 ++- Moose Development/Moose/Core/Cargo.lua | 589 +++++++++--------- Moose Development/Moose/Core/Point.lua | 5 + 3 files changed, 396 insertions(+), 296 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_Troops.lua b/Moose Development/Moose/AI/AI_Cargo_Troops.lua index 7cb69ab0c..dd2104ccc 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Troops.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Troops.lua @@ -48,6 +48,8 @@ function AI_CARGO_TROOPS:New( CargoCarrier, CargoGroup, CombatRadius ) self:AddTransition( "Unboarding", "Unloaded", "Unloaded" ) self:AddTransition( "*", "Monitor", "*" ) + self:AddTransition( "*", "Follow", "Following" ) + self:AddTransition( "*", "Guard", "Guarding" ) self:__Monitor( 1 ) self:__Load( 1 ) @@ -56,38 +58,94 @@ function AI_CARGO_TROOPS:New( CargoCarrier, CargoGroup, CombatRadius ) end +--- Follow Infantry to the Carrier. +-- @param #AI_CARGO_TROOPS self +-- @return #AI_CARGO_TROOPS +function AI_CARGO_TROOPS:FollowToCarrier( Me ) + + self = Me + + self:F( { self = self:GetClassNameAndID(), CargoGroup = self.CargoGroup:GetName() } ) + + -- We check if the Cargo is near to the CargoCarrier. + if self.CargoGroup:IsNear( self.CargoCarrier, 5 ) then + + -- The Cargo does not need to follow the Carrier. + self:Guard() + + else + + -- The Cargo needs to continue to follow the Carrier. + if self:Is( "Following" ) then + + -- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2 + self.CargoGroup.CargoSet:ForEach( + --- @param Core.Cargo#CARGO Cargo + function( Cargo ) + local CargoUnit = Cargo.CargoObject -- Wrapper.Unit#UNIT + self:F( { UnitName = CargoUnit:GetName() } ) + + if CargoUnit:IsAlive() then + + local InfantryGroup = CargoUnit:GetGroup() + self:F( { GroupName = InfantryGroup:GetName() } ) + + local Waypoints = {} + + -- Calculate the new Route. + local FromCoord = InfantryGroup:GetCoordinate() + local FromGround = FromCoord:WaypointGround( 10, "Diamond" ) + table.insert( Waypoints, FromGround ) + + local ToCoord = self.CargoCarrier:GetCoordinate() + local ToGround = ToCoord:WaypointGround( 10, "Diamond" ) + table.insert( Waypoints, ToGround ) + + local TaskRoute = InfantryGroup:TaskFunction( "AI_CARGO_TROOPS.FollowToCarrier", self ) + + 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 ) -- Move after a random seconds to the Route. See the Route method for details. + end + end + ) + end + end +end + + --- @param #AI_CARGO_TROOPS self -- @param Wrapper.Unit#UNIT CargoCarrier function AI_CARGO_TROOPS:onafterMonitor( CargoCarrier, From, Event, To ) self:F( { CargoCarrier, From, Event, To } ) if CargoCarrier and CargoCarrier:IsAlive() then - if self.Coordinate then + if self.CarrierCoordinate then local Coordinate = CargoCarrier:GetCoordinate() self.Zone:Scan( { Object.Category.UNIT } ) if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then --- if self:Is( "Unloaded" ) then --- -- There are no enemies within combat range. Load the CargoCarrier. --- self:__Load( 1 ) --- end + if self:Is( "Unloaded" ) or self:Is( "Guarding" ) then + -- There are no enemies within combat range. Load the CargoCarrier. + self:__Load( 1 ) + end else if self:Is( "Loaded" ) then -- There are enemies within combat range. Unload the CargoCarrier. self:__Unload( 1 ) end end - if self:Is( "Unloaded" ) then - if not Coordinate:IsAtCoordinate2D( self.Coordinate, 2 ) then - --self.CargoGroup:RouteTo( Coordinate, 30 ) + if self:Is( "Guarding" ) then + if not self.CargoGroup:IsNear( CargoCarrier, 5 ) then + self:Follow() end end - - else - self.Coordinate = CargoCarrier:GetCoordinate() end + self.CarrierCoordinate = CargoCarrier:GetCoordinate() end - self:__Monitor( 1 ) + self:__Monitor( -5 ) end @@ -167,7 +225,23 @@ function AI_CARGO_TROOPS:onafterUnloaded( CargoCarrier, From, Event, To ) self:F( { CargoCarrier, From, Event, To } ) if CargoCarrier and CargoCarrier:IsAlive() then + self:Guard() + self.CargoCarrier = CargoCarrier CargoCarrier:RouteResume() end end + + +--- @param #AI_CARGO_TROOPS self +-- @param Wrapper.Unit#UNIT CargoCarrier +function AI_CARGO_TROOPS:onafterFollow( CargoCarrier, From, Event, To ) + self:F( { CargoCarrier, From, Event, To } ) + + self:F( "Follow" ) + if CargoCarrier and CargoCarrier:IsAlive() then + self:FollowToCarrier( self ) + end + +end + diff --git a/Moose Development/Moose/Core/Cargo.lua b/Moose Development/Moose/Core/Cargo.lua index 66f9c04c8..f767c5ea7 100644 --- a/Moose Development/Moose/Core/Cargo.lua +++ b/Moose Development/Moose/Core/Cargo.lua @@ -491,17 +491,22 @@ end -- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision). -- @return #boolean function CARGO:IsNear( PointVec2, NearRadius ) - self:F( { PointVec2, NearRadius } ) + self:F( { PointVec2 = PointVec2, NearRadius = NearRadius } ) - --local Distance = PointVec2:DistanceFromPointVec2( self.CargoObject:GetPointVec2() ) - local Distance = PointVec2:Get2DDistance( self.CargoObject:GetPointVec2() ) - self:T( Distance ) - - if Distance <= NearRadius then - return true - else - return false + if self.CargoObject:IsAlive() then + --local Distance = PointVec2:DistanceFromPointVec2( self.CargoObject:GetPointVec2() ) + self:F( { CargoObjectName = self.CargoObject:GetName() } ) + self:F( { CargoObjectVec2 = self.CargoObject:GetVec2() } ) + self:F( { PointVec2 = PointVec2:GetVec2() } ) + local Distance = PointVec2:Get2DDistance( self.CargoObject:GetPointVec2() ) + self:T( Distance ) + + if Distance <= NearRadius then + return true + end end + + return false end --- Get the current PointVec2 of the cargo. @@ -746,7 +751,7 @@ do -- CARGO_UNIT function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius ) self:F( { From, Event, To, ToPointVec2, NearRadius } ) - NearRadius = NearRadius or 25 + NearRadius = NearRadius or 100 local Angle = 180 local Speed = 60 @@ -804,7 +809,7 @@ do -- CARGO_UNIT function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius ) self:F( { From, Event, To, ToPointVec2, NearRadius } ) - NearRadius = NearRadius or 25 + NearRadius = NearRadius or 100 local Angle = 180 local Speed = 10 @@ -831,7 +836,7 @@ do -- CARGO_UNIT function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius ) self:F( { From, Event, To, ToPointVec2, NearRadius } ) - NearRadius = NearRadius or 25 + NearRadius = NearRadius or 100 self.CargoInAir = self.CargoObject:InAir() @@ -1149,299 +1154,299 @@ do -- CARGO_GROUP ClassName = "CARGO_GROUP", } ---- CARGO_GROUP constructor. --- @param #CARGO_GROUP self --- @param Wrapper.Group#GROUP CargoGroup --- @param #string Type --- @param #string Name --- @param #number ReportRadius (optional) --- @param #number NearRadius (optional) --- @return #CARGO_GROUP -function CARGO_GROUP:New( CargoGroup, Type, Name, ReportRadius ) - local self = BASE:Inherit( self, CARGO_REPORTABLE:New( CargoGroup, Type, Name, 0, ReportRadius ) ) -- #CARGO_GROUP - self:F( { Type, Name, ReportRadius } ) - - self.CargoObject = CargoGroup - self:SetDeployed( false ) - self.CargoGroup = CargoGroup + --- CARGO_GROUP constructor. + -- @param #CARGO_GROUP self + -- @param Wrapper.Group#GROUP CargoGroup + -- @param #string Type + -- @param #string Name + -- @param #number ReportRadius (optional) + -- @param #number NearRadius (optional) + -- @return #CARGO_GROUP + function CARGO_GROUP:New( CargoGroup, Type, Name, ReportRadius ) + local self = BASE:Inherit( self, CARGO_REPORTABLE:New( CargoGroup, Type, Name, 0, ReportRadius ) ) -- #CARGO_GROUP + self:F( { Type, Name, ReportRadius } ) - local WeightGroup = 0 + self.CargoObject = CargoGroup + self:SetDeployed( false ) + self.CargoGroup = CargoGroup + + local WeightGroup = 0 + + for UnitID, UnitData in pairs( CargoGroup:GetUnits() ) do + local Unit = UnitData -- Wrapper.Unit#UNIT + local WeightUnit = Unit:GetDesc().massEmpty + WeightGroup = WeightGroup + WeightUnit + local CargoUnit = CARGO_UNIT:New( Unit, Type, Unit:GetName(), WeightUnit ) + self.CargoSet:Add( CargoUnit:GetName(), CargoUnit ) + end - for UnitID, UnitData in pairs( CargoGroup:GetUnits() ) do - local Unit = UnitData -- Wrapper.Unit#UNIT - local WeightUnit = Unit:GetDesc().massEmpty - WeightGroup = WeightGroup + WeightUnit - local CargoUnit = CARGO_UNIT:New( Unit, Type, Unit:GetName(), WeightUnit ) - self.CargoSet:Add( CargoUnit:GetName(), CargoUnit ) + self:SetWeight( WeightGroup ) + + self:T( { "Weight Cargo", WeightGroup } ) + + -- Cargo objects are added to the _DATABASE and SET_CARGO objects. + _EVENTDISPATCHER:CreateEventNewCargo( self ) + + self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead ) + self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead ) + self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead ) + + self:SetEventPriority( 4 ) + + return self end - self:SetWeight( WeightGroup ) + --- @param #CARGO_GROUP self + -- @param Core.Event#EVENTDATA EventData + function CARGO_GROUP:OnEventCargoDead( EventData ) - self:T( { "Weight Cargo", WeightGroup } ) - - -- Cargo objects are added to the _DATABASE and SET_CARGO objects. - _EVENTDISPATCHER:CreateEventNewCargo( self ) - - self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead ) - self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead ) - self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead ) - - self:SetEventPriority( 4 ) - - return self -end - ---- @param #CARGO_GROUP self --- @param Core.Event#EVENTDATA EventData -function CARGO_GROUP:OnEventCargoDead( EventData ) - - local Destroyed = false - - if self:IsDestroyed() or self:IsUnLoaded() then - Destroyed = true - for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do - local Cargo = CargoData -- #CARGO - if Cargo:IsAlive() then - Destroyed = false - else - Cargo:Destroyed() - end - end - else - local CarrierName = self.CargoCarrier:GetName() - if CarrierName == EventData.IniDCSUnitName then - MESSAGE:New( "Cargo is lost from carrier " .. CarrierName, 15 ):ToAll() + local Destroyed = false + + if self:IsDestroyed() or self:IsUnLoaded() then Destroyed = true - self.CargoCarrier:ClearCargo() + for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do + local Cargo = CargoData -- #CARGO + if Cargo:IsAlive() then + Destroyed = false + else + Cargo:Destroyed() + end + end + else + local CarrierName = self.CargoCarrier:GetName() + if CarrierName == EventData.IniDCSUnitName then + MESSAGE:New( "Cargo is lost from carrier " .. CarrierName, 15 ):ToAll() + Destroyed = true + self.CargoCarrier:ClearCargo() + end end - end - - if Destroyed then - self:Destroyed() - self:E( { "Cargo group destroyed" } ) - end - -end - ---- Enter Boarding State. --- @param #CARGO_GROUP self --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) - self:F( { CargoCarrier.UnitName, From, Event, To } ) - - local NearRadius = NearRadius or 25 - - if From == "UnLoaded" then - - -- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2 - self.CargoSet:ForEach( - function( Cargo, ... ) - Cargo:__Board( 1, CargoCarrier, NearRadius, ... ) - end, ... - ) - self:__Boarding( 1, CargoCarrier, NearRadius, ... ) + if Destroyed then + self:Destroyed() + self:E( { "Cargo group destroyed" } ) + end + end - -end ---- Enter Loaded State. --- @param #CARGO_GROUP self --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onenterLoaded( From, Event, To, CargoCarrier, ... ) - self:F( { From, Event, To, CargoCarrier, ...} ) + --- Enter Boarding State. + -- @param #CARGO_GROUP self + -- @param Wrapper.Unit#UNIT CargoCarrier + -- @param #string Event + -- @param #string From + -- @param #string To + function CARGO_GROUP:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) + self:F( { CargoCarrier.UnitName, From, Event, To } ) + + local NearRadius = NearRadius or 25 + + if From == "UnLoaded" then - if From == "UnLoaded" then - -- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier. + -- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2 + self.CargoSet:ForEach( + function( Cargo, ... ) + Cargo:__Board( 1, CargoCarrier, NearRadius, ... ) + end, ... + ) + + self:__Boarding( 1, CargoCarrier, NearRadius, ... ) + end + + end + + --- Enter Loaded State. + -- @param #CARGO_GROUP self + -- @param Wrapper.Unit#UNIT CargoCarrier + -- @param #string Event + -- @param #string From + -- @param #string To + function CARGO_GROUP:onenterLoaded( From, Event, To, CargoCarrier, ... ) + self:F( { From, Event, To, CargoCarrier, ...} ) + + if From == "UnLoaded" then + -- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier. + for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do + Cargo:Load( CargoCarrier ) + end + end + + --self.CargoObject:Destroy() + self.CargoCarrier = CargoCarrier + + end + + --- Leave Boarding State. + -- @param #CARGO_GROUP self + -- @param Wrapper.Unit#UNIT CargoCarrier + -- @param #string Event + -- @param #string From + -- @param #string To + function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) + self:F( { CargoCarrier.UnitName, From, Event, To } ) + + local NearRadius = NearRadius or 100 + + local Boarded = true + local Cancelled = false + local Dead = true + + self.CargoSet:Flush() + + -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do - Cargo:Load( CargoCarrier ) - end - end + self:T( { Cargo:GetName(), Cargo.current } ) + + + if not Cargo:is( "Loaded" ) + and (not Cargo:is( "Destroyed" )) then -- If one or more units of a group defined as CARGO_GROUP died, the CARGO_GROUP:Board() command does not trigger the CARGO_GRUOP:OnEnterLoaded() function. + Boarded = false + end + + if Cargo:is( "UnLoaded" ) then + Cancelled = true + end - --self.CargoObject:Destroy() - self.CargoCarrier = CargoCarrier + if not Cargo:is( "Destroyed" ) then + Dead = false + end + + end -end - ---- Leave Boarding State. --- @param #CARGO_GROUP self --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) - self:F( { CargoCarrier.UnitName, From, Event, To } ) - - local NearRadius = NearRadius or 25 - - local Boarded = true - local Cancelled = false - local Dead = true - - self.CargoSet:Flush() - - -- 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 } ) - - - if not Cargo:is( "Loaded" ) - and (not Cargo:is( "Destroyed" )) then -- If one or more units of a group defined as CARGO_GROUP died, the CARGO_GROUP:Board() command does not trigger the CARGO_GRUOP:OnEnterLoaded() function. - Boarded = false - end - - if Cargo:is( "UnLoaded" ) then - Cancelled = true - end - - if not Cargo:is( "Destroyed" ) then - Dead = false - end - - end - - if not Dead then - - if not Cancelled then - if not Boarded then - self:__Boarding( 1, CargoCarrier, NearRadius, ... ) + if not Dead then + + if not Cancelled then + if not Boarded then + self:__Boarding( 1, CargoCarrier, NearRadius, ... ) + else + self:F("Group Cargo is loaded") + self:__Load( 1, CargoCarrier, ... ) + end else - self:F("Group Cargo is loaded") - self:__Load( 1, CargoCarrier, ... ) + self:__CancelBoarding( 1, CargoCarrier, NearRadius, ... ) end else - self:__CancelBoarding( 1, CargoCarrier, NearRadius, ... ) + self:__Destroyed( 1, CargoCarrier, NearRadius, ... ) end - else - self:__Destroyed( 1, CargoCarrier, NearRadius, ... ) + end -end - ---- Get the amount of cargo units in the group. --- @param #CARGO_GROUP self --- @return #CARGO_GROUP -function CARGO_GROUP:GetCount() - return self.CargoSet:Count() -end - - ---- Enter UnBoarding State. --- @param #CARGO_GROUP self --- @param Core.Point#POINT_VEC2 ToPointVec2 --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) - self:F( {From, Event, To, ToPointVec2, NearRadius } ) - - NearRadius = NearRadius or 25 - - local Timer = 1 - - if From == "Loaded" then - - if self.CargoObject then - self.CargoObject:Destroy() - end - - -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 - self.CargoSet:ForEach( - function( Cargo, NearRadius ) - - Cargo:__UnBoard( Timer, ToPointVec2, NearRadius ) - Timer = Timer + 10 - end, { NearRadius } - ) - - - self:__UnBoarding( 1, ToPointVec2, NearRadius, ... ) + --- Get the amount of cargo units in the group. + -- @param #CARGO_GROUP self + -- @return #CARGO_GROUP + function CARGO_GROUP:GetCount() + return self.CargoSet:Count() end -end ---- Leave UnBoarding State. --- @param #CARGO_GROUP self --- @param Core.Point#POINT_VEC2 ToPointVec2 --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) - self:F( { From, Event, To, ToPointVec2, NearRadius } ) - - --local NearRadius = NearRadius or 25 - - local Angle = 180 - local Speed = 10 - local Distance = 5 - - if From == "UnBoarding" then - local UnBoarded = true - - -- 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.current ) - if not Cargo:is( "UnLoaded" ) then - UnBoarded = false + --- Enter UnBoarding State. + -- @param #CARGO_GROUP self + -- @param Core.Point#POINT_VEC2 ToPointVec2 + -- @param #string Event + -- @param #string From + -- @param #string To + function CARGO_GROUP:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) + self:F( {From, Event, To, ToPointVec2, NearRadius } ) + + NearRadius = NearRadius or 100 + + local Timer = 1 + + if From == "Loaded" then + + if self.CargoObject then + self.CargoObject:Destroy() end - end - if UnBoarded then - return true - else + -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 + self.CargoSet:ForEach( + function( Cargo, NearRadius ) + + Cargo:__UnBoard( Timer, ToPointVec2, NearRadius ) + Timer = Timer + 10 + end, { NearRadius } + ) + + self:__UnBoarding( 1, ToPointVec2, NearRadius, ... ) end - - return false - end -end + end ---- UnBoard Event. --- @param #CARGO_GROUP self --- @param Core.Point#POINT_VEC2 ToPointVec2 --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) - self:F( { From, Event, To, ToPointVec2, NearRadius } ) - - --local NearRadius = NearRadius or 25 - - self:__UnLoad( 1, ToPointVec2, ... ) -end - - - ---- Enter UnLoaded State. --- @param #CARGO_GROUP self --- @param Core.Point#POINT_VEC2 --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onenterUnLoaded( From, Event, To, ToPointVec2, ... ) - self:F( { From, Event, To, ToPointVec2 } ) - - if From == "Loaded" then - - -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 - self.CargoSet:ForEach( - function( Cargo ) - --Cargo:UnLoad( ToPointVec2 ) - local RandomVec2=ToPointVec2:GetRandomPointVec2InRadius(10) - Cargo:UnLoad( RandomVec2 ) + --- Leave UnBoarding State. + -- @param #CARGO_GROUP self + -- @param Core.Point#POINT_VEC2 ToPointVec2 + -- @param #string Event + -- @param #string From + -- @param #string To + function CARGO_GROUP:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) + self:F( { From, Event, To, ToPointVec2, NearRadius } ) + + --local NearRadius = NearRadius or 25 + + local Angle = 180 + local Speed = 10 + local Distance = 5 + + if From == "UnBoarding" then + local UnBoarded = true + + -- 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.current ) + if not Cargo:is( "UnLoaded" ) then + UnBoarded = false + end end - ) - + + if UnBoarded then + return true + else + self:__UnBoarding( 1, ToPointVec2, NearRadius, ... ) + end + + return false + end + end + + --- UnBoard Event. + -- @param #CARGO_GROUP self + -- @param Core.Point#POINT_VEC2 ToPointVec2 + -- @param #string Event + -- @param #string From + -- @param #string To + function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) + self:F( { From, Event, To, ToPointVec2, NearRadius } ) -end + --local NearRadius = NearRadius or 25 + + self:__UnLoad( 1, ToPointVec2, ... ) + end + + + + --- Enter UnLoaded State. + -- @param #CARGO_GROUP self + -- @param Core.Point#POINT_VEC2 + -- @param #string Event + -- @param #string From + -- @param #string To + function CARGO_GROUP:onenterUnLoaded( From, Event, To, ToPointVec2, ... ) + self:F( { From, Event, To, ToPointVec2 } ) + + if From == "Loaded" then + + -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 + self.CargoSet:ForEach( + function( Cargo ) + --Cargo:UnLoad( ToPointVec2 ) + local RandomVec2=ToPointVec2:GetRandomPointVec2InRadius(10) + Cargo:UnLoad( RandomVec2 ) + end + ) + + end + + end --- Respawn the cargo when destroyed @@ -1464,21 +1469,37 @@ end -- @param #CARGO_GROUP self -- @param Core.Point#COORDINATE Coordinate function CARGO_GROUP:RouteTo( Coordinate ) - self:F( ) + self:F( {Coordinate = Coordinate } ) - --local NearRadius = NearRadius or 25 - - if From == "UnLoaded" then - - -- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2 - self.CargoSet:ForEach( - function( Cargo, Coordinate ) - Cargo.CargoObject:RouteTo( Coordinate ) - end, Coordinate - ) + -- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2 + self.CargoSet:ForEach( + function( Cargo ) + Cargo.CargoObject:RouteGroundTo( Coordinate, 10, "vee", 0 ) + end + ) + end + + --- Check if Cargo is near to the Carrier. + -- The Cargo is near to the Carrier if the first unit of the Cargo Group is within NearRadius. + -- @param #CARGO_GROUP self + -- @param Wrapper.Group#GROUP CargoCarrier + -- @param #number NearRadius + -- @return #boolean The Cargo is near to the Carrier. + -- @return #nil The Cargo is not near to the Carrier. + function CARGO_GROUP:IsNear( CargoCarrier, NearRadius ) + self:F( {NearRadius = NearRadius } ) + + local FirstCargo = self.CargoSet:GetFirst() -- #CARGO + + if FirstCargo then + if FirstCargo:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) then + self:F( "Near" ) + return true + end end + return nil end end -- CARGO_GROUP diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index df0a3d21a..0a787216a 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -258,9 +258,14 @@ do -- COORDINATE --- Returns if the 2 coordinates are at the same 2D position. -- @param #COORDINATE self + -- @param #COORDINATE Coordinate + -- @param #number Precision -- @return #boolean true if at the same position. function COORDINATE:IsAtCoordinate2D( Coordinate, Precision ) + self:F( { Coordinate = Coordinate:GetVec2() } ) + self:F( { self = self:GetVec2() } ) + local x = Coordinate.x local z = Coordinate.z From 9759640d52264a3042366b4b46209b0753714a2a Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Tue, 27 Mar 2018 13:46:55 +0200 Subject: [PATCH 05/10] comment --- Moose Development/Moose/AI/AI_Cargo_Troops.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_Troops.lua b/Moose Development/Moose/AI/AI_Cargo_Troops.lua index dd2104ccc..eecf65e2b 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Troops.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Troops.lua @@ -22,7 +22,7 @@ AI_CARGO_TROOPS = { Coordinate = nil -- Core.Point#COORDINATE, } ---- Creates a new AI_CARGO_TROOPS object +--- Creates a new AI_CARGO_TROOPS object. -- @param #AI_CARGO_TROOPS self -- @return #AI_CARGO_TROOPS function AI_CARGO_TROOPS:New( CargoCarrier, CargoGroup, CombatRadius ) From 21a7bac4e0938071fbd3ec34c6a3cf11086b46fb Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Tue, 27 Mar 2018 13:56:53 +0200 Subject: [PATCH 06/10] added file --- Moose Setup/Moose.files | 1 + 1 file changed, 1 insertion(+) diff --git a/Moose Setup/Moose.files b/Moose Setup/Moose.files index 1e575f0f2..49a8fc08b 100644 --- a/Moose Setup/Moose.files +++ b/Moose Setup/Moose.files @@ -61,6 +61,7 @@ AI/AI_Cap.lua AI/AI_Cas.lua AI/AI_Bai.lua AI/AI_Formation.lua +AI/AI_Cargo_Troops.lua Actions/Act_Assign.lua Actions/Act_Route.lua From b1a1c6c5523c77b10dc513c6233d84f80146f146 Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Tue, 27 Mar 2018 14:16:04 +0200 Subject: [PATCH 07/10] -- The infantry must only be 5 meters near. --- Moose Development/Moose/AI/AI_Cargo_Troops.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_Troops.lua b/Moose Development/Moose/AI/AI_Cargo_Troops.lua index eecf65e2b..55494fa21 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Troops.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Troops.lua @@ -158,7 +158,7 @@ function AI_CARGO_TROOPS:onafterLoad( CargoCarrier, From, Event, To ) if CargoCarrier and CargoCarrier:IsAlive() then CargoCarrier:RouteStop() self:Board() - self.CargoGroup:Board( CargoCarrier, 100 ) + self.CargoGroup:Board( CargoCarrier, 5 ) end end From e22e7f2c584c9948f0823d391d0c0bf5a8546264 Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Tue, 27 Mar 2018 15:03:07 +0200 Subject: [PATCH 08/10] -- Fix issue SET_AIRBASE does not update #817. --- Moose Development/Moose/Core/Set.lua | 37 +++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index b02e76168..9d8dd721e 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -152,13 +152,15 @@ function SET_BASE:Remove( ObjectName ) local Object = self.Set[ObjectName] - self:F3( { ObjectName, Object } ) + self:F( { ObjectName, Object } ) if Object then for Index, Key in ipairs( self.Index ) do + self:F( { Index = Index, Key = Key } ) if Key == ObjectName then table.remove( self.Index, Index ) self.Set[ObjectName] = nil + self:Flush(self) break end end @@ -3864,7 +3866,7 @@ function SET_AIRBASE:RemoveAirbasesByName( RemoveAirbaseNames ) local RemoveAirbaseNamesArray = ( type( RemoveAirbaseNames ) == "table" ) and RemoveAirbaseNames or { RemoveAirbaseNames } for RemoveAirbaseID, RemoveAirbaseName in pairs( RemoveAirbaseNamesArray ) do - self:Remove( RemoveAirbaseName.AirbaseName ) + self:Remove( RemoveAirbaseName ) end return self @@ -3926,12 +3928,41 @@ end function SET_AIRBASE:FilterStart() if _DATABASE then - self:_FilterStart() + + -- We use the BaseCaptured event, which is generated by DCS when a base got captured. + self:HandleEvent( EVENTS.BaseCaptured ) + + -- We initialize the first set. + for ObjectName, Object in pairs( self.Database ) do + if self:IsIncludeObject( Object ) then + self:Add( ObjectName, Object ) + else + self:RemoveAirbasesByName( ObjectName ) + end + end end return self end +--- Starts the filtering. +-- @param #SET_AIRBASE self +-- @param Core.Event#EVENT EventData +-- @return #SET_AIRBASE self +function SET_AIRBASE:OnEventBaseCaptured(EventData) + + -- When a base got captured, we reevaluate the set. + for ObjectName, Object in pairs( self.Database ) do + if self:IsIncludeObject( Object ) then + -- We add captured bases on yet in the set. + self:Add( ObjectName, Object ) + else + -- We remove captured bases that are not anymore part of the set. + self:RemoveAirbasesByName( ObjectName ) + end + end + +end --- Handles the Database to check on an event (birth) that the Object was added in the Database. -- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event! From 747777b29701b7c55601c7d0431ed63b85b89a8a Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Tue, 27 Mar 2018 15:10:14 +0200 Subject: [PATCH 09/10] -- Fix issue SET_AIRBASE does not update #817. --- Moose Development/Moose/Core/Set.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index 9d8dd721e..939973fd1 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -152,11 +152,8 @@ function SET_BASE:Remove( ObjectName ) local Object = self.Set[ObjectName] - self:F( { ObjectName, Object } ) - if Object then for Index, Key in ipairs( self.Index ) do - self:F( { Index = Index, Key = Key } ) if Key == ObjectName then table.remove( self.Index, Index ) self.Set[ObjectName] = nil From 7a579a0ab5e8c7ad71f480c18bed8cf160f730c3 Mon Sep 17 00:00:00 2001 From: FlightControl_Master Date: Tue, 27 Mar 2018 20:59:37 +0200 Subject: [PATCH 10/10] -- Fixed a lot of issues with cargo when the cargo representative is destroyed. --- .../Moose/AI/AI_Cargo_Troops.lua | 4 +- Moose Development/Moose/Core/Cargo.lua | 75 ++++++++++--------- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_Troops.lua b/Moose Development/Moose/AI/AI_Cargo_Troops.lua index 55494fa21..8c6491753 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Troops.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Troops.lua @@ -126,7 +126,7 @@ function AI_CARGO_TROOPS:onafterMonitor( CargoCarrier, From, Event, To ) local Coordinate = CargoCarrier:GetCoordinate() self.Zone:Scan( { Object.Category.UNIT } ) if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then - if self:Is( "Unloaded" ) or self:Is( "Guarding" ) then + if self:Is( "Unloaded" ) or self:Is( "Guarding" ) or self:Is( "Following" ) then -- There are no enemies within combat range. Load the CargoCarrier. self:__Load( 1 ) end @@ -158,7 +158,7 @@ function AI_CARGO_TROOPS:onafterLoad( CargoCarrier, From, Event, To ) if CargoCarrier and CargoCarrier:IsAlive() then CargoCarrier:RouteStop() self:Board() - self.CargoGroup:Board( CargoCarrier, 5 ) + self.CargoGroup:Board( CargoCarrier, 25 ) end end diff --git a/Moose Development/Moose/Core/Cargo.lua b/Moose Development/Moose/Core/Cargo.lua index f767c5ea7..4cc5eac2b 100644 --- a/Moose Development/Moose/Core/Cargo.lua +++ b/Moose Development/Moose/Core/Cargo.lua @@ -760,41 +760,44 @@ do -- CARGO_UNIT if From == "Loaded" then - local CargoCarrier = self.CargoCarrier -- Wrapper.Controllable#CONTROLLABLE + if not self:IsDestroyed() then - local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2() - local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees. - local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) - - - local CargoRoutePointVec2 = CargoCarrierPointVec2:Translate( RouteDistance, CargoDeployHeading ) - - - -- if there is no ToPointVec2 given, then use the CargoRoutePointVec2 - ToPointVec2 = ToPointVec2 or CargoRoutePointVec2 - local DirectionVec3 = CargoCarrierPointVec2:GetDirectionVec3(ToPointVec2) - local Angle = CargoCarrierPointVec2:GetAngleDegrees(DirectionVec3) - - local CargoDeployPointVec2 = CargoCarrierPointVec2:Translate( DeployDistance, Angle ) - - local FromPointVec2 = CargoCarrierPointVec2 - - -- Respawn the group... - if self.CargoObject then - self.CargoObject:ReSpawn( CargoDeployPointVec2:GetVec3(), CargoDeployHeading ) - self:F( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } ) - self.CargoCarrier = nil - - local Points = {} - Points[#Points+1] = CargoCarrierPointVec2:WaypointGround( Speed ) - - Points[#Points+1] = ToPointVec2:WaypointGround( Speed ) + local CargoCarrier = self.CargoCarrier -- Wrapper.Controllable#CONTROLLABLE - local TaskRoute = self.CargoObject:TaskRoute( Points ) - self.CargoObject:SetTask( TaskRoute, 1 ) - + local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2() + local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees. + local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) + + + local CargoRoutePointVec2 = CargoCarrierPointVec2:Translate( RouteDistance, CargoDeployHeading ) - self:__UnBoarding( 1, ToPointVec2, NearRadius ) + + -- if there is no ToPointVec2 given, then use the CargoRoutePointVec2 + ToPointVec2 = ToPointVec2 or CargoRoutePointVec2 + local DirectionVec3 = CargoCarrierPointVec2:GetDirectionVec3(ToPointVec2) + local Angle = CargoCarrierPointVec2:GetAngleDegrees(DirectionVec3) + + local CargoDeployPointVec2 = CargoCarrierPointVec2:Translate( DeployDistance, Angle ) + + local FromPointVec2 = CargoCarrierPointVec2 + + -- Respawn the group... + if self.CargoObject then + self.CargoObject:ReSpawn( CargoDeployPointVec2:GetVec3(), CargoDeployHeading ) + self:F( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } ) + self.CargoCarrier = nil + + local Points = {} + Points[#Points+1] = CargoCarrierPointVec2:WaypointGround( Speed ) + + Points[#Points+1] = ToPointVec2:WaypointGround( Speed ) + + local TaskRoute = self.CargoObject:TaskRoute( Points ) + self.CargoObject:SetTask( TaskRoute, 1 ) + + + self:__UnBoarding( 1, ToPointVec2, NearRadius ) + end end end @@ -949,7 +952,7 @@ do -- CARGO_UNIT self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } ) - if CargoCarrier and CargoCarrier:IsAlive() then + if CargoCarrier and CargoCarrier:IsAlive() and self.CargoObject and self.CargoObject:IsAlive() then if CargoCarrier:InAir() == false then if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then self:__Load( 1, CargoCarrier, ... ) @@ -1200,9 +1203,11 @@ do -- CARGO_GROUP -- @param Core.Event#EVENTDATA EventData function CARGO_GROUP:OnEventCargoDead( EventData ) + self:_F( { "Dead Event", EventData = EventData } ) + local Destroyed = false - if self:IsDestroyed() or self:IsUnLoaded() then + if self:IsDestroyed() or self:IsUnLoaded() or self:IsBoarding() then Destroyed = true for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do local Cargo = CargoData -- #CARGO @@ -1392,7 +1397,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.current ) - if not Cargo:is( "UnLoaded" ) then + if not Cargo:is( "UnLoaded" ) and not Cargo:IsDestroyed() then UnBoarded = false end end