From 832941494bd2e4cd2f51e3db46b18e967e23003a Mon Sep 17 00:00:00 2001 From: Shafik Date: Wed, 5 Nov 2025 12:35:55 +0200 Subject: [PATCH 1/5] [FIXED] `dcsgroup:getUnit(1)` nil pointer --- Moose Development/Moose/Wrapper/Group.lua | 36 +++++++++++++++-------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index 1c38db672..0109a9719 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -1058,9 +1058,12 @@ function GROUP:GetTypeName() local DCSGroup = self:GetDCSObject() if DCSGroup then - local GroupTypeName = DCSGroup:getUnit(1):getTypeName() - --self:T3( GroupTypeName ) - return( GroupTypeName ) + local unit = DCSGroup:getUnit(1) + if unit then + local GroupTypeName = unit:getTypeName() + --self:T3( GroupTypeName ) + return( GroupTypeName ) + end end return nil @@ -1075,9 +1078,12 @@ function GROUP:GetNatoReportingName() local DCSGroup = self:GetDCSObject() if DCSGroup then - local GroupTypeName = DCSGroup:getUnit(1):getTypeName() - --self:T3( GroupTypeName ) - return UTILS.GetReportingName(GroupTypeName) + local unit = DCSGroup:getUnit(1) + if unit then + local GroupTypeName = unit:getTypeName() + --self:T3( GroupTypeName ) + return UTILS.GetReportingName(GroupTypeName) + end end return "Bogey" @@ -1093,9 +1099,12 @@ function GROUP:GetPlayerName() local DCSGroup = self:GetDCSObject() if DCSGroup then - local PlayerName = DCSGroup:getUnit(1):getPlayerName() - --self:T3( PlayerName ) - return( PlayerName ) + local unit = DCSGroup:getUnit(1) + if unit then + local PlayerName = unit:getPlayerName() + --self:T3( PlayerName ) + return( PlayerName ) + end end return nil @@ -1111,9 +1120,12 @@ function GROUP:GetCallsign() local DCSGroup = self:GetDCSObject() if DCSGroup then - local GroupCallSign = DCSGroup:getUnit(1):getCallsign() - --self:T3( GroupCallSign ) - return GroupCallSign + local unit = DCSGroup:getUnit(1) + if unit then + local GroupCallSign = unit:getCallsign() + --self:T3( GroupCallSign ) + return GroupCallSign + end end BASE:E( { "Cannot GetCallsign", Positionable = self, Alive = self:IsAlive() } ) From 17d1cf673d62482f6992679615b2180adb19ee07 Mon Sep 17 00:00:00 2001 From: Shafik Date: Thu, 6 Nov 2025 12:23:13 +0200 Subject: [PATCH 2/5] [ADDED] IsRed, IsBlue and IsNeutral to IDENTIFIABLE --- .../Moose/Wrapper/Identifiable.lua | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Moose Development/Moose/Wrapper/Identifiable.lua b/Moose Development/Moose/Wrapper/Identifiable.lua index 8561d5b2b..4f2928cb5 100644 --- a/Moose Development/Moose/Wrapper/Identifiable.lua +++ b/Moose Development/Moose/Wrapper/Identifiable.lua @@ -170,6 +170,27 @@ function IDENTIFIABLE:GetCoalition() return nil end +--- Returns true if identifiable is of RED coalition. +-- @param #IDENTIFIABLE self +-- @return #boolean If the identifiable is red. +function IDENTIFIABLE:IsRed() + return self:GetCoalition() == coalition.side.RED +end + +--- Returns true if identifiable is of BLUE coalition. +-- @param #IDENTIFIABLE self +-- @return #boolean If the identifiable is blue. +function IDENTIFIABLE:IsBlue() + return self:GetCoalition() == coalition.side.BLUE +end + +--- Returns true if identifiable is of NEUTRAL coalition. +-- @param #IDENTIFIABLE self +-- @return #boolean If the identifiable is neutral. +function IDENTIFIABLE:IsNeutral() + return self:GetCoalition() == coalition.side.NEUTRAL +end + --- Returns the name of the coalition of the Identifiable. -- @param #IDENTIFIABLE self -- @return #string The name of the coalition. From caf2b4e73645fa605ddff7087d558870588e4723 Mon Sep 17 00:00:00 2001 From: leka1986 <83298840+leka1986@users.noreply.github.com> Date: Sat, 8 Nov 2025 02:47:56 +0100 Subject: [PATCH 3/5] Update CTLD.lua Added ability to drop "Sets" from 2 and up will be sets, else it will be like before. Changed _PackCratesNearby to handle all cargo within the range instead of the nearest. --- Moose Development/Moose/Ops/CTLD.lua | 210 +++++++++++++++++++-------- 1 file changed, 152 insertions(+), 58 deletions(-) diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 372d32afc..062804662 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -1561,9 +1561,8 @@ function CTLD:New(Coalition, Prefixes, Alias) self.movetroopsdistance = 5000 self.returntroopstobase = true -- if set to false, troops would stay after deployment inside a load zone. self.troopdropzoneradius = 100 - + self.buildPairSeparation = 25 self.loadSavedCrates = true - self.VehicleMoveFormation = AI.Task.VehicleFormation.VEE -- added support Hercules Mod @@ -4235,23 +4234,62 @@ function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop) end -- let\'s get going if canbuild then + local notified=false -- loop again for _,_build in pairs(buildables) do local build = _build -- #CTLD.Buildable if build.CanBuild then - self:_CleanUpCrates(crates,build,number) - self:_RefreshLoadCratesMenu(Group,Unit) - if self.buildtime and self.buildtime > 0 then + local required = build.Required or 1 + if required < 1 then required = 1 end + local full = math.floor((build.Found or 0)/required) + if full < 1 then full = 1 end + + local sep = self.buildPairSeparation or 25 + local hdg = (Unit:GetHeading()+180)%360 + local lat = (hdg+90)%360 + local base = Unit:GetCoordinate():Translate(20,hdg) + + if full == 1 then + local cratesNow, numberNow = self:_FindCratesNearby(Group,Unit, finddist,true,true) + self:_CleanUpCrates(cratesNow,build,numberNow) + self:_RefreshLoadCratesMenu(Group,Unit) + if self.buildtime and self.buildtime > 0 then local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate(),MultiDrop) buildtimer:Start(self.buildtime) - self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group) + if not notified then + self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group) + notified=true + end self:__CratesBuildStarted(1,Group,Unit,build.Name) + else + self:_BuildObjectFromCrates(Group,Unit,build,false,nil,MultiDrop) + end else - self:_BuildObjectFromCrates(Group,Unit,build,false,nil,MultiDrop) + local start = -((full-1)*sep)/2 + for n=1,full do + local cratesNow, numberNow = self:_FindCratesNearby(Group,Unit, finddist,true,true) + self:_CleanUpCrates(cratesNow,build,numberNow) + self:_RefreshLoadCratesMenu(Group,Unit) + local off = start + (n-1)*sep + local coord = base:Translate(off,lat):GetVec2() + local b = { Name=build.Name, Required=build.Required, Template=build.Template, CanBuild=true, Type=build.Type, Coord=coord } + if self.buildtime and self.buildtime > 0 then + local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,b,false,Group:GetCoordinate(),MultiDrop) + buildtimer:Start(self.buildtime) + if not notified then + self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group) + notified=true + end + self:__CratesBuildStarted(1,Group,Unit,build.Name) + else + self:_BuildObjectFromCrates(Group,Unit,b,false,nil,MultiDrop) + end + end end end end end + else if not Engineering then self:_SendMessage(string.format("No crates within %d meters!",finddist), 10, false, Group) end end -- number > 0 @@ -4273,28 +4311,37 @@ function CTLD:_PackCratesNearby(Group, Unit) -- get nearby vehicles local location = Group:GetCoordinate() -- get coordinate of group using function - local nearestGroups = SET_GROUP:New():FilterCoalitions("blue"):FilterZones({ZONE_RADIUS:New("TempZone", location:GetVec2(), self.PackDistance, false)}):FilterOnce() -- get all groups withing PackDistance from group using function - -- get template name of all vehicles in zone + local nearestGroups = SET_GROUP:New():FilterCoalitions("blue"):FilterZones({ZONE_RADIUS:New("TempZone", location:GetVec2(), self.PackDistance, false)}):FilterOnce() + + local packedAny = false -- determine if group is packable for _, _Group in pairs(nearestGroups.Set) do -- convert #SET_GROUP to a list of Wrapper.Group#GROUP + local didPackThisGroup = false for _, _Template in pairs(_DATABASE.Templates.Groups) do -- iterate through the database of templates - if (string.match(_Group:GetName(), _Template.GroupName)) then -- check if the Wrapper.Group#GROUP near the player is in the list of templates by name - -- generate crates and destroy group + if string.match(_Group:GetName(), _Template.GroupName) then -- check if the Wrapper.Group#GROUP near the player is in the list of templates by name for _, _entry in pairs(self.Cargo_Crates) do -- iterate through #CTLD_CARGO - if (_entry.Templates[1] == _Template.GroupName) then -- check if the #CTLD_CARGO matches the template name - _Group:Destroy() -- if a match is found destroy the Wrapper.Group#GROUP near the player + if _entry.Templates[1] == _Template.GroupName then -- check if the #CTLD_CARGO matches the template name + _Group:Destroy() self:_GetCrates(Group, Unit, _entry, nil, false, true) -- spawn the appropriate crates near the player self:_RefreshLoadCratesMenu(Group,Unit) -- call the refresher to show the crates in the menu self:__CratesPacked(1,Group,Unit,_entry) - return true + packedAny = true + didPackThisGroup = true + break end end end + if didPackThisGroup then break end end end + + if not packedAny then self:_SendMessage("Nothing to pack at this distance pilot!",10,false,Group) return false + end + + return true end --- (Internal) Function to repair nearby vehicles / FOBs @@ -4513,7 +4560,8 @@ function CTLD:_CleanUpCrates(Crates,Build,Number) if name == nametype then -- matching crate type table.insert(destIDs,thisID) found = found + 1 - nowcrate:GetPositionable():Destroy(false) + local pos = nowcrate:GetPositionable() + if pos then pos:Destroy(false) end nowcrate.Positionable = nil nowcrate.HasBeenDropped = false end @@ -5597,34 +5645,50 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit) local needed=list[1]:GetCratesNeeded() or 1 table.sort(list,function(a,b)return a:GetID()=needed then + local sets=math.floor(#list/(needed>0 and needed or 1)) + if sets>0 then + local parentLabel=string.format("%d. %s (%d SET)",lineIndex,cName,sets) + local parentMenu=MENU_GROUP:New(Group,parentLabel,dropCratesMenu) + for s=1,sets do local chunk={} - for n=i,i+needed-1 do - table.insert(chunk,list[n]) - end - local label=string.format("%d. %s",lineIndex,cName) + for n=i,i+needed-1 do table.insert(chunk,list[n]) end table.insert(self.CrateGroupList[Unit:GetName()],chunk) - local setIndex=#self.CrateGroupList[Unit:GetName()] - MENU_GROUP_COMMAND:New(Group,label,dropCratesMenu,self._UnloadSingleCrateSet,self,Group,Unit,setIndex) i=i+needed - else - local chunk={} - for n=i,#list do - table.insert(chunk,list[n]) - end - local label=string.format("%d. %s %d/%d",lineIndex,cName,left,needed) - table.insert(self.CrateGroupList[Unit:GetName()],chunk) - local setIndex=#self.CrateGroupList[Unit:GetName()] - MENU_GROUP_COMMAND:New(Group,label,dropCratesMenu,self._UnloadSingleCrateSet,self,Group,Unit,setIndex) - i=#list+1 end + for q=1,sets do + local qm=MENU_GROUP:New(Group,string.format("Drop %d Set%s",q,q>1 and "s" or ""),parentMenu) + MENU_GROUP_COMMAND:New(Group,"Drop",qm,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) + local uName=UnitArg:GetName() + for k=1,qty do + local lst=selfArg.CrateGroupList and selfArg.CrateGroupList[uName] + if not lst then break end + local idx=nil + for j=1,#lst do + local ch=lst[j] + local first=ch and ch[1] + if first and (not first:WasDropped()) and first:GetName()==cNameArg and #ch>=neededArg then idx=j break end + end + if not idx then break end + selfArg:_UnloadSingleCrateSet(GroupArg,UnitArg,idx) + end + end,self,Group,Unit,cName,needed,q) + end + lineIndex=lineIndex+1 + end + if i<=#list then + local left=#list-i+1 + local chunk={} + for n=i,#list do table.insert(chunk,list[n]) end + table.insert(self.CrateGroupList[Unit:GetName()],chunk) + local setIndex=#self.CrateGroupList[Unit:GetName()] + local label=string.format("%d. %s %d/%d",lineIndex,cName,left,needed) + MENU_GROUP_COMMAND:New(Group,label,dropCratesMenu,self._UnloadSingleCrateSet,self,Group,Unit,setIndex) lineIndex=lineIndex+1 end end else + -------------------------------------------------------------------- -------------------------------------------------------------------- -- one-step (enhanced) menu -------------------------------------------------------------------- @@ -5642,39 +5706,69 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit) local needed=list[1]:GetCratesNeeded() or 1 table.sort(list,function(a,b)return a:GetID()=needed then + local sets=math.floor(#list/(needed>0 and needed or 1)) + if sets>0 then + local parentLabel=string.format("%d. %s (%d SET)",lineIndex,cName,sets) + local parentMenu=MENU_GROUP:New(Group,parentLabel,dropCratesMenu) + for s=1,sets do local chunk={} - for n=i,i+needed-1 do - table.insert(chunk,list[n]) - end - local label=string.format("%d. %s",lineIndex,cName) + for n=i,i+needed-1 do table.insert(chunk,list[n]) end table.insert(self.CrateGroupList[Unit:GetName()],chunk) - local setIndex=#self.CrateGroupList[Unit:GetName()] - local mSet=MENU_GROUP:New(Group,label,dropCratesMenu) - MENU_GROUP_COMMAND:New(Group,"Drop",mSet,self._UnloadSingleCrateSet,self,Group,Unit,setIndex) - if not ( self:IsUnitInAir(Unit) and self:IsFixedWing(Unit) ) then - MENU_GROUP_COMMAND:New(Group,"Drop and build",mSet,self._DropSingleAndBuild,self,Group,Unit,setIndex) - end i=i+needed - else - local chunk={} - for n=i,#list do - table.insert(chunk,list[n]) - end - local label=string.format("%d. %s %d/%d",lineIndex,cName,left,needed) - table.insert(self.CrateGroupList[Unit:GetName()],chunk) - local setIndex=#self.CrateGroupList[Unit:GetName()] - MENU_GROUP_COMMAND:New(Group,label,dropCratesMenu,self._UnloadSingleCrateSet,self,Group,Unit,setIndex) - i=#list+1 end + for q=1,sets do + local qm=MENU_GROUP:New(Group,string.format("Drop %d Set%s",q,q>1 and "s" or ""),parentMenu) + MENU_GROUP_COMMAND:New(Group,"Drop",qm,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) + local uName=UnitArg:GetName() + for k=1,qty do + local lst=selfArg.CrateGroupList and selfArg.CrateGroupList[uName] + if not lst then break end + local idx=nil + for j=1,#lst do + local ch=lst[j] + local first=ch and ch[1] + if first and (not first:WasDropped()) and first:GetName()==cNameArg and #ch>=neededArg then idx=j break end + end + if not idx then break end + selfArg:_UnloadSingleCrateSet(GroupArg,UnitArg,idx) + end + end,self,Group,Unit,cName,needed,q) + if not ( self:IsUnitInAir(Unit) and self:IsFixedWing(Unit) ) then + MENU_GROUP_COMMAND:New(Group,"Drop and build",qm,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) + local uName=UnitArg:GetName() + for k=1,qty do + local lst=selfArg.CrateGroupList and selfArg.CrateGroupList[uName] + if not lst then break end + local idx=nil + for j=1,#lst do + local ch=lst[j] + local first=ch and ch[1] + if first and (not first:WasDropped()) and first:GetName()==cNameArg and #ch>=neededArg then idx=j break end + end + if not idx then break end + selfArg:_UnloadSingleCrateSet(GroupArg,UnitArg,idx) + end + selfArg:_BuildCrates(GroupArg,UnitArg) + end,self,Group,Unit,cName,needed,q) + end + end + lineIndex=lineIndex+1 + end + if i<=#list then + local left=#list-i+1 + local chunk={} + for n=i,#list do table.insert(chunk,list[n]) end + table.insert(self.CrateGroupList[Unit:GetName()],chunk) + local setIndex=#self.CrateGroupList[Unit:GetName()] + local label=string.format("%d. %s %d/%d",lineIndex,cName,left,needed) + MENU_GROUP_COMMAND:New(Group,label,dropCratesMenu,self._UnloadSingleCrateSet,self,Group,Unit,setIndex) lineIndex=lineIndex+1 end end end end + --- (Internal) Function to unload a single Troop group by ID. -- @param #CTLD self -- @param Wrapper.Group#GROUP Group The calling group. @@ -8472,7 +8566,7 @@ end local injecttroops = CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass) self:InjectTroops(dropzone,injecttroops,self.surfacetypes,self.useprecisecoordloads,structure,timestamp) end - elseif self.loadSavedCrates and ((type(groupname) == "string" and groupname == "STATIC") or cargotype == CTLD_CARGO.Enum.REPAIR) then + elseif self.loadSavedCrates and (type(groupname) == "string" and groupname == "STATIC") or cargotype == CTLD_CARGO.Enum.REPAIR then local dropzone = ZONE_RADIUS:New("DropZone",vec2,20) local injectstatic = nil if cargotype == CTLD_CARGO.Enum.VEHICLE or cargotype == CTLD_CARGO.Enum.FOB then From aa4cf37aed31e29e6d1d186cc8d2df6f84dc046a Mon Sep 17 00:00:00 2001 From: leka1986 <83298840+leka1986@users.noreply.github.com> Date: Sat, 8 Nov 2025 02:52:23 +0100 Subject: [PATCH 4/5] Clean up comments in CTLD.lua Removed unnecessary comment lines in CTLD.lua. --- Moose Development/Moose/Ops/CTLD.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 062804662..481ae557f 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -5688,7 +5688,6 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit) end else - -------------------------------------------------------------------- -------------------------------------------------------------------- -- one-step (enhanced) menu -------------------------------------------------------------------- From 7b44e7a3f645a969a7e4a3316b558b91861cdaf8 Mon Sep 17 00:00:00 2001 From: leka1986 <83298840+leka1986@users.noreply.github.com> Date: Sun, 9 Nov 2025 02:16:02 +0100 Subject: [PATCH 5/5] Update CTLD.lua Removed quantity menu if there is only one set. --- Moose Development/Moose/Ops/CTLD.lua | 72 ++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 481ae557f..b29ac8866 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -5655,9 +5655,8 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit) table.insert(self.CrateGroupList[Unit:GetName()],chunk) i=i+needed end - for q=1,sets do - local qm=MENU_GROUP:New(Group,string.format("Drop %d Set%s",q,q>1 and "s" or ""),parentMenu) - MENU_GROUP_COMMAND:New(Group,"Drop",qm,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) + if sets==1 then + MENU_GROUP_COMMAND:New(Group,"Drop",parentMenu,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) local uName=UnitArg:GetName() for k=1,qty do local lst=selfArg.CrateGroupList and selfArg.CrateGroupList[uName] @@ -5671,7 +5670,26 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit) if not idx then break end selfArg:_UnloadSingleCrateSet(GroupArg,UnitArg,idx) end - end,self,Group,Unit,cName,needed,q) + end,self,Group,Unit,cName,needed,1) + else + for q=1,sets do + local qm=MENU_GROUP:New(Group,string.format("Drop %d Set%s",q,q>1 and "s" or ""),parentMenu) + MENU_GROUP_COMMAND:New(Group,"Drop",qm,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) + local uName=UnitArg:GetName() + for k=1,qty do + local lst=selfArg.CrateGroupList and selfArg.CrateGroupList[uName] + if not lst then break end + local idx=nil + for j=1,#lst do + local ch=lst[j] + local first=ch and ch[1] + if first and (not first:WasDropped()) and first:GetName()==cNameArg and #ch>=neededArg then idx=j break end + end + if not idx then break end + selfArg:_UnloadSingleCrateSet(GroupArg,UnitArg,idx) + end + end,self,Group,Unit,cName,needed,q) + end end lineIndex=lineIndex+1 end @@ -5715,9 +5733,8 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit) table.insert(self.CrateGroupList[Unit:GetName()],chunk) i=i+needed end - for q=1,sets do - local qm=MENU_GROUP:New(Group,string.format("Drop %d Set%s",q,q>1 and "s" or ""),parentMenu) - MENU_GROUP_COMMAND:New(Group,"Drop",qm,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) + if sets==1 then + MENU_GROUP_COMMAND:New(Group,"Drop",parentMenu,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) local uName=UnitArg:GetName() for k=1,qty do local lst=selfArg.CrateGroupList and selfArg.CrateGroupList[uName] @@ -5731,9 +5748,9 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit) if not idx then break end selfArg:_UnloadSingleCrateSet(GroupArg,UnitArg,idx) end - end,self,Group,Unit,cName,needed,q) + end,self,Group,Unit,cName,needed,1) if not ( self:IsUnitInAir(Unit) and self:IsFixedWing(Unit) ) then - MENU_GROUP_COMMAND:New(Group,"Drop and build",qm,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) + MENU_GROUP_COMMAND:New(Group,"Drop and build",parentMenu,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) local uName=UnitArg:GetName() for k=1,qty do local lst=selfArg.CrateGroupList and selfArg.CrateGroupList[uName] @@ -5748,7 +5765,44 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit) selfArg:_UnloadSingleCrateSet(GroupArg,UnitArg,idx) end selfArg:_BuildCrates(GroupArg,UnitArg) + end,self,Group,Unit,cName,needed,1) + end + else + for q=1,sets do + local qm=MENU_GROUP:New(Group,string.format("Drop %d Set%s",q,q>1 and "s" or ""),parentMenu) + MENU_GROUP_COMMAND:New(Group,"Drop",qm,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) + local uName=UnitArg:GetName() + for k=1,qty do + local lst=selfArg.CrateGroupList and selfArg.CrateGroupList[uName] + if not lst then break end + local idx=nil + for j=1,#lst do + local ch=lst[j] + local first=ch and ch[1] + if first and (not first:WasDropped()) and first:GetName()==cNameArg and #ch>=neededArg then idx=j break end + end + if not idx then break end + selfArg:_UnloadSingleCrateSet(GroupArg,UnitArg,idx) + end end,self,Group,Unit,cName,needed,q) + if not ( self:IsUnitInAir(Unit) and self:IsFixedWing(Unit) ) then + MENU_GROUP_COMMAND:New(Group,"Drop and build",qm,function(selfArg,GroupArg,UnitArg,cNameArg,neededArg,qty) + local uName=UnitArg:GetName() + for k=1,qty do + local lst=selfArg.CrateGroupList and selfArg.CrateGroupList[uName] + if not lst then break end + local idx=nil + for j=1,#lst do + local ch=lst[j] + local first=ch and ch[1] + if first and (not first:WasDropped()) and first:GetName()==cNameArg and #ch>=neededArg then idx=j break end + end + if not idx then break end + selfArg:_UnloadSingleCrateSet(GroupArg,UnitArg,idx) + end + selfArg:_BuildCrates(GroupArg,UnitArg) + end,self,Group,Unit,cName,needed,q) + end end end lineIndex=lineIndex+1