diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 113bfff23..6f8412eb5 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -435,13 +435,14 @@ OPSGROUP.CargoStatus={ --- OpsGroup version. -- @field #string version -OPSGROUP.version="0.7.2" +OPSGROUP.version="0.7.3" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO: AI on/off. +-- TODO: Emission on/off. -- TODO: Invisible/immortal. -- TODO: F10 menu. -- TODO: Add pseudo function. @@ -1112,7 +1113,7 @@ function OPSGROUP:GetVelocity(UnitName) return nil end ---- Get current heading of the group. +--- Get current heading of the group or (optionally) of a specific unit of the group. -- @param #OPSGROUP self -- @param #string UnitName (Optional) Get heading of a specific unit of the group. Default is from the first existing unit in the group. -- @return #number Current heading of the group in degrees. @@ -1181,7 +1182,7 @@ function OPSGROUP:GetOrientation(UnitName) return nil end ---- Get current orientation of the first unit in the group. +--- Get current "X" orientation of the first unit in the group. -- @param #OPSGROUP self -- @param #string UnitName (Optional) Get orientation of a specific unit of the group. Default is the first existing unit of the group. -- @return DCS#Vec3 Orientation X parallel to where the "nose" is pointing. @@ -1736,6 +1737,13 @@ function OPSGROUP:IsNotCarrier() return self.carrierStatus==OPSGROUP.CarrierStatus.NOTCARRIER end +--- Check if the group is a carrier. +-- @param #OPSGROUP self +-- @return #boolean If true, group is a carrier. +function OPSGROUP:IsCarrier() + return not self:IsNotCarrier() +end + --- Check if the group is picking up cargo. -- @param #OPSGROUP self -- @return #boolean If true, group is picking up. @@ -1765,6 +1773,13 @@ function OPSGROUP:IsUnloading() end +--- Check if the group is assigned as cargo. +-- @param #OPSGROUP self +-- @return #boolean If true, group is cargo. +function OPSGROUP:IsCargo() + return not self:IsNotCargo() +end + --- Check if the group is **not** cargo. -- @param #OPSGROUP self -- @return #boolean If true, group is *not* cargo. @@ -4548,6 +4563,12 @@ function OPSGROUP:onafterElementDead(From, Event, To, Element) end end end + + if self:IsCarrier() then + if self.cargoTransport then + self.cargoTransport:CarrierGroupDead() + end + end end @@ -4693,7 +4714,7 @@ end -- @param #string Event Event. -- @param #string To To state. function OPSGROUP:onafterDead(From, Event, To) - self:T(self.lid..string.format("Group dead at t=%.3f", timer.getTime())) + self:I(self.lid..string.format("Group dead at t=%.3f", timer.getTime())) -- Is dead now. self.isDead=true @@ -4708,11 +4729,17 @@ function OPSGROUP:onafterDead(From, Event, To) mission:GroupDead(self) end + + -- Inform all transports in the queue that this carrier group is dead now. + for i,_transport in pairs(self.cargoqueue) do + local transport=_transport --Ops.OpsTransport#OPSTRANSPORT + transport:DeadCarrierGroup(self) + end -- Delete waypoints so they are re-initialized at the next spawn. self.waypoints=nil self.groupinitialized=false - + -- Stop in a sec. self:__Stop(-5) end @@ -5037,16 +5064,16 @@ function OPSGROUP:AddOpsTransport(OpsTransport) -- Add this group as carrier for the transport. OpsTransport:_AddCarrier(self) - --Add to cargo queue table.insert(self.cargoqueue, OpsTransport) + -- Debug message. self:I(self.lid.."FF adding transport to carrier, #self.cargoqueue="..#self.cargoqueue) return self end ---- Delete a cargo transport assignment from the cargo queue +--- Delete a cargo transport assignment from the cargo queue. -- @param #OPSGROUP self -- @param Ops.OpsTransport#OPSTRANSPORT CargoTransport Cargo transport do be deleted. -- @return #OPSGROUP self diff --git a/Moose Development/Moose/Ops/OpsTransport.lua b/Moose Development/Moose/Ops/OpsTransport.lua index 2c03b672f..92a9ff9ff 100644 --- a/Moose Development/Moose/Ops/OpsTransport.lua +++ b/Moose Development/Moose/Ops/OpsTransport.lua @@ -3,6 +3,9 @@ -- ## Main Features: -- -- * Transport troops from A to B. +-- * Supports ground, naval and airborne (airplanes and helicopters) units as carriers +-- * Use combined forces (ground, naval, air) to transport the troops. +-- * Additional FSM events to hook into and customize your mission design. -- -- === -- @@ -55,7 +58,8 @@ -- -- # The OPSTRANSPORT Concept -- --- Transport OPSGROUPS using carriers such as APCs, helicopters or airplanes. +-- This class simulates troop transport using carriers such as APCs, ships helicopters or airplanes. The carriers and transported groups need to be OPSGROUPS (see ARMYGROUP, NAVYGROUP and FLIGHTGROUP classed). +-- -- -- @field #OPSTRANSPORT OPSTRANSPORT = { @@ -97,14 +101,14 @@ _OPSTRANSPORTID=0 --- Army Group version. -- @field #string version -OPSTRANSPORT.version="0.0.5" +OPSTRANSPORT.version="0.0.6" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- DONE: Add start conditions. --- TODO: Check carrier(s) dead. +-- DONE: Check carrier(s) dead. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Constructor @@ -164,6 +168,9 @@ function OPSTRANSPORT:New(GroupSet, Pickupzone, Deployzone) self:AddTransition("*", "Loaded", "*") self:AddTransition("*", "Unloaded", "*") + self:AddTransition("*", "DeadCarrierUnit", "*") + self:AddTransition("*", "DeadCarrierGroup", "*") + self:AddTransition("*", "DeadCarrierAll", "*") -- Call status update. self:__Status(-1) @@ -313,16 +320,19 @@ end -- @return #OPSTRANSPORT self function OPSTRANSPORT:_AddCarrier(CarrierGroup) + -- Check that this is not already an assigned carrier. if not self:IsCarrier(CarrierGroup) then -- Increase carrier count. self.Ncarrier=self.Ncarrier+1 - -- Set trans + -- Set transport status to SCHEDULED. self:SetCarrierTransportStatus(CarrierGroup, OPSTRANSPORT.Status.SCHEDULED) + -- Call scheduled event. self:Scheduled() + -- Add carrier to table. table.insert(self.carriers, CarrierGroup) end @@ -330,6 +340,32 @@ function OPSTRANSPORT:_AddCarrier(CarrierGroup) return self end +--- Remove group from the current carrier list/table. +-- @param #OPSTRANSPORT self +-- @param Ops.OpsGroup#OPSGROUP CarrierGroup Carrier OPSGROUP. +-- @return #OPSTRANSPORT self +function OPSTRANSPORT:_DelCarrier(CarrierGroup) + + if self:IsCarrier(CarrierGroup) then + + for i,_carrier in pairs(self.carriers) do + local carrier=_carrier --Ops.OpsGroup#OPSGROUP + if carrier.groupname==CarrierGroup.groupname then + self:I(self.lid..string.format("Removing carrier %s", CarrierGroup.groupname)) + table.remove(self.carriers, i) + end + end + + if #self.carriers==0 then + self:DeadCarrierAll() + end + + end + + return self +end + + --- Set transport start and stop time. -- @param #OPSTRANSPORT self -- @param #string ClockStart Time the transport is started, e.g. "05:00" for 5 am. If specified as a #number, it will be relative (in seconds) to the current mission time. Default is 5 seconds after mission was added. @@ -560,7 +596,7 @@ function OPSTRANSPORT:onafterStatus(From, Event, To) local fsmstate=self:GetState() -- Info text. - local text=string.format("%s [%s --> %s]: Ncargo=%d/%d, Ncarrier=%d", fsmstate:upper(), self.pickupzone:GetName(), self.deployzone:GetName(), self.Ncargo, self.Ndelivered, self.Ncarrier) + local text=string.format("%s [%s --> %s]: Ncargo=%d/%d, Ncarrier=%d/%d", fsmstate:upper(), self.pickupzone:GetName(), self.deployzone:GetName(), self.Ncargo, self.Ndelivered, #self.carriers,self.Ncarrier) text=text..string.format("\nCargos:") for _,_cargo in pairs(self.cargos) do @@ -648,6 +684,30 @@ function OPSTRANSPORT:onafterUnloaded(From, Event, To, OpsGroup) self:I(self.lid..string.format("Unloaded OPSGROUP %s", OpsGroup:GetName())) end +--- On after "DeadCarrierGroup" event. +-- @param #OPSTRANSPORT self +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +-- @param Ops.OpsGroup#OPSGROUP OpsGroup Carrier OPSGROUP that is dead. +function OPSTRANSPORT:onafterDeadCarrierGroup(From, Event, To, OpsGroup) + self:I(self.lid..string.format("Carrier OPSGROUP %s dead!", OpsGroup:GetName())) + -- Remove group from carrier list/table. + self:_DelCarrier(OpsGroup) +end + +--- On after "DeadCarrierAll" event. +-- @param #OPSTRANSPORT self +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +function OPSTRANSPORT:onafterDeadCarrierAll(From, Event, To) + self:I(self.lid..string.format("ALL Carrier OPSGROUPs are dead! Setting stage to PLANNED if not all cargo was delivered.")) + if not self:IsDelivered() then + self:Planned() + end +end + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Misc Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -776,7 +836,7 @@ function OPSTRANSPORT:_CreateCargoGroupData(group) return cargo end ---- Get an OPSGROUIP +--- Get an OPSGROUP from a given OPSGROUP or GROUP object. If the object is a GROUUP, an OPSGROUP is created automatically. -- @param #OPSTRANSPORT self -- @param Core.Base#BASE Object The object, which can be a GROUP or OPSGROUP. -- @return Ops.OpsGroup#OPSGROUP Ops Group.