mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-07-16 22:22:25 +00:00
Merge remote-tracking branch 'origin/master' into branch
This commit is contained in:
@@ -193,6 +193,7 @@ CTLD_CARGO = {
|
||||
-- @param Wrapper.Unit#UNIT Unit
|
||||
-- @return #boolean Outcome
|
||||
function CTLD_CARGO:UnitCanCarry(Unit)
|
||||
if not Unit then return false end
|
||||
if self.TypeNames == nil then return true end
|
||||
local typename = Unit:GetTypeName() or "none"
|
||||
if self.TypeNames[typename] then
|
||||
@@ -2910,6 +2911,28 @@ end
|
||||
-- @return #CTLD self
|
||||
function CTLD:_LoadTroopsQuantity(Group, Unit, Cargo, quantity)
|
||||
local n = math.max(1, tonumber(quantity) or 1)
|
||||
|
||||
-- landed or hovering over load zone?
|
||||
local grounded = not self:IsUnitInAir(Unit)
|
||||
local hoverload = self:CanHoverLoad(Unit)
|
||||
|
||||
-- check if we are in LOAD zone
|
||||
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
|
||||
if not inzone then
|
||||
inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
|
||||
end
|
||||
|
||||
if not inzone then
|
||||
self:_SendMessage("You are not close enough to a logistics zone!", 10, false, Group)
|
||||
if not self.debug then return self end
|
||||
elseif not grounded and not hoverload then
|
||||
self:_SendMessage("You need to land or hover in position to load!", 10, false, Group)
|
||||
if not self.debug then return self end
|
||||
elseif self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
|
||||
self:_SendMessage("You need to open the door(s) to load troops!", 10, false, Group)
|
||||
if not self.debug then return self end
|
||||
end
|
||||
|
||||
local prevSuppress = self.suppressmessages
|
||||
self.suppressmessages = true
|
||||
for i = 1, n do
|
||||
@@ -2954,11 +2977,10 @@ function CTLD:_AddTroopQuantityMenus(Group, Unit, parentMenu, cargoObj)
|
||||
if capacitySets < maxQuantity then maxQuantity = capacitySets end
|
||||
end
|
||||
for quantity = 1, maxQuantity do
|
||||
local m = MENU_GROUP:New(Group, tostring(quantity), parentMenu)
|
||||
if quantity == 1 then
|
||||
MENU_GROUP_COMMAND:New(Group, "Load", m, self._LoadTroops, self, Group, Unit, cargoObj)
|
||||
MENU_GROUP_COMMAND:New(Group, tostring(quantity), parentMenu, self._LoadTroops, self, Group, Unit, cargoObj)
|
||||
else
|
||||
MENU_GROUP_COMMAND:New(Group, "Load", m, self._LoadTroopsQuantity, self, Group, Unit, cargoObj, quantity)
|
||||
MENU_GROUP_COMMAND:New(Group, tostring(quantity), parentMenu, self._LoadTroopsQuantity, self, Group, Unit, cargoObj, quantity)
|
||||
end
|
||||
end
|
||||
return self
|
||||
@@ -3137,6 +3159,17 @@ function CTLD:_AddCrateQuantityMenus(Group, Unit, parentMenu, cargoObj, stockSum
|
||||
return self
|
||||
end
|
||||
|
||||
--- User overrideable function to determine if a unit can get crates.
|
||||
-- @param #CTLD self
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
-- @param Wrapper.Unit#UNIT Unit
|
||||
-- @param #table Config Configuration entry for the unit.
|
||||
-- @param #number quantity Number of crate sets requested.
|
||||
-- @param #boolean quiet If true, do not send messages to the user.
|
||||
function CTLD:CanGetUnits(Group, Unit, Config, quantity, quiet)
|
||||
return true
|
||||
end
|
||||
|
||||
--- (Internal) Spawn a “Get units” entry for a C-130J-30 at load zone.
|
||||
-- @param #CTLD self
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
@@ -3167,6 +3200,9 @@ function CTLD:_C130GetUnits(Group, Unit, Name)
|
||||
self:_SendMessage("You are not close enough to a logistics zone!",10,false,Group)
|
||||
return self
|
||||
end
|
||||
if not self:CanGetUnits(Group, Unit, cfg, 1, false) then
|
||||
return self
|
||||
end
|
||||
|
||||
local coord = Unit:GetCoordinate() or Group:GetCoordinate()
|
||||
local capabilities = self:_GetUnitCapabilities(Unit)
|
||||
@@ -3514,9 +3550,9 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack, quiet, suppress
|
||||
Cargo:RemoveStock(requestedSets)
|
||||
self:_RefreshCrateQuantityMenus(Group, Unit, Cargo)
|
||||
end
|
||||
local text = string.format("Crates for %s have been positioned near you!",cratename)
|
||||
local text = string.format("%d crates for %s have been positioned near you!",number,cratename)
|
||||
if drop then
|
||||
text = string.format("Crates for %s have been dropped!",cratename)
|
||||
text = string.format("%d crates for %s have been dropped!",number,cratename)
|
||||
self:__CratesDropped(1, Group, Unit, droppedcargo)
|
||||
else
|
||||
if not quiet then
|
||||
@@ -3612,7 +3648,7 @@ end
|
||||
function CTLD:_ListCratesNearby( _group, _unit)
|
||||
self:T(self.lid .. " _ListCratesNearby")
|
||||
local finddist = self.CrateDistance or 35
|
||||
local crates,number,loadedbygc,indexgc = self:_FindCratesNearby(_group,_unit, finddist,true,true) -- #table
|
||||
local crates,number,loadedbygc,indexgc = self:_FindCratesNearby(_group,_unit, finddist,true,true,true) -- #table
|
||||
if number > 0 or indexgc > 0 then
|
||||
local text = REPORT:New("Crates Found Nearby:")
|
||||
text:Add("------------------------------------------------------------")
|
||||
@@ -3711,7 +3747,7 @@ end
|
||||
function CTLD:_RemoveCratesNearby(_group, _unit)
|
||||
self:T(self.lid.." _RemoveCratesNearby")
|
||||
local finddist=self.CrateDistance or 35
|
||||
local crates,number=self:_FindCratesNearby(_group,_unit,finddist,true,true)
|
||||
local crates,number=self:_FindCratesNearby(_group,_unit,finddist,true,true,true)
|
||||
if number>0 then
|
||||
local removedIDs={}
|
||||
local text=REPORT:New("Removing Crates Found Nearby:")
|
||||
@@ -3824,7 +3860,7 @@ function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight, ignoretype
|
||||
self:T(self.lid .. " Loading restricted: " .. tostring(restricted))
|
||||
local staticpos = static:GetCoordinate() --or dcsunitpos
|
||||
local cando = cargo:UnitCanCarry(_unit)
|
||||
if ignoretype == true then cando = true end
|
||||
if ignoretype == true then cando = true restricted = false end
|
||||
self:T(self.lid .. " Unit can carry: " .. tostring(cando))
|
||||
--- Testing
|
||||
local distance=self:_GetDistance(location,staticpos)
|
||||
@@ -4618,7 +4654,7 @@ function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop)
|
||||
finddist=self.EngineerSearch
|
||||
finddist=self.EngineerSearch
|
||||
end
|
||||
local crates,number = self:_FindCratesNearby(Group,Unit, finddist,true,true) -- #table
|
||||
local crates,number = self:_FindCratesNearby(Group,Unit,finddist,true,true,not Engineering) -- #table
|
||||
local buildables = {}
|
||||
local foundbuilds = false
|
||||
local canbuild = false
|
||||
@@ -6411,9 +6447,11 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit)
|
||||
-- @param Wrapper.Unit#UNIT Unit The calling unit.
|
||||
-- @param #number chunkID the Cargo ID
|
||||
-- @return #CTLD self
|
||||
function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID)
|
||||
function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID, qty)
|
||||
self:T(self.lid .. " _UnloadSingleTroopByID chunkID=" .. tostring(chunkID))
|
||||
|
||||
qty = qty or 1
|
||||
|
||||
local droppingatbase = false
|
||||
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit, CTLD.CargoZoneType.LOAD)
|
||||
if not inzone then
|
||||
@@ -6452,80 +6490,92 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID)
|
||||
return self
|
||||
end
|
||||
|
||||
local deployedTroopsByName = {}
|
||||
local deployedEngineersByName = {}
|
||||
|
||||
-- Drop the FIRST cargo in that chunk
|
||||
local foundCargo = chunk[1]
|
||||
if not foundCargo then
|
||||
self:_SendMessage(string.format("No troop cargo at chunk %d!", chunkID), 10, false, Group)
|
||||
if not self.debug then return self end
|
||||
return self
|
||||
end
|
||||
for n = 1, qty do
|
||||
local foundCargo = chunk[1]
|
||||
if not foundCargo then break end
|
||||
|
||||
local cType = foundCargo:GetType()
|
||||
local name = foundCargo:GetName() or "none"
|
||||
local tmpl = foundCargo:GetTemplates() or {}
|
||||
local zoneradius = self.troopdropzoneradius or 100
|
||||
local factor = 1
|
||||
if isHerc then
|
||||
factor = foundCargo:GetCratesNeeded() or 1
|
||||
zoneradius = Unit:GetVelocityMPS() or 100
|
||||
end
|
||||
local zone = ZONE_GROUP:New(string.format("Unload zone-%s", unitName), Group, zoneradius * factor)
|
||||
local randomcoord = zone:GetRandomCoordinate(10, 30 * factor)
|
||||
local heading = Group:GetHeading() or 0
|
||||
|
||||
if grounded or hoverunload then
|
||||
randomcoord = Group:GetCoordinate()
|
||||
local Angle = (heading + 270) % 360
|
||||
if isHerc or isHook then
|
||||
Angle = (heading + 180) % 360
|
||||
end
|
||||
local offset = hoverunload and self.TroopUnloadDistHover or self.TroopUnloadDistGround
|
||||
local cType = foundCargo:GetType()
|
||||
local name = foundCargo:GetName() or "none"
|
||||
local tmpl = foundCargo:GetTemplates() or {}
|
||||
local zoneradius = self.troopdropzoneradius or 100
|
||||
local factor = 1
|
||||
if isHerc then
|
||||
offset = self.TroopUnloadDistGroundHerc or 25
|
||||
factor = foundCargo:GetCratesNeeded() or 1
|
||||
zoneradius = Unit:GetVelocityMPS() or 100
|
||||
end
|
||||
if isHook then
|
||||
offset = self.TroopUnloadDistGroundHook or 15
|
||||
if hoverunload and self.TroopUnloadDistHoverHook then
|
||||
offset = self.TroopUnloadDistHoverHook or 5
|
||||
local zone = ZONE_GROUP:New(string.format("Unload zone-%s", unitName), Group, zoneradius * factor)
|
||||
local randomcoord = zone:GetRandomCoordinate(10, 30 * factor)
|
||||
local heading = Group:GetHeading() or 0
|
||||
|
||||
if grounded or hoverunload then
|
||||
randomcoord = Group:GetCoordinate()
|
||||
local Angle = (heading + 270) % 360
|
||||
if isHerc or isHook then
|
||||
Angle = (heading + 180) % 360
|
||||
end
|
||||
local offset = hoverunload and self.TroopUnloadDistHover or self.TroopUnloadDistGround
|
||||
if isHerc then
|
||||
offset = self.TroopUnloadDistGroundHerc or 25
|
||||
end
|
||||
if isHook then
|
||||
offset = self.TroopUnloadDistGroundHook or 15
|
||||
if hoverunload and self.TroopUnloadDistHoverHook then
|
||||
offset = self.TroopUnloadDistHoverHook or 5
|
||||
end
|
||||
end
|
||||
randomcoord:Translate(offset, Angle, nil, true)
|
||||
end
|
||||
|
||||
local tempcount = 0
|
||||
if isHook then
|
||||
tempcount = self.ChinookTroopCircleRadius or 5
|
||||
end
|
||||
for _, _template in pairs(tmpl) do
|
||||
self.TroopCounter = self.TroopCounter + 1
|
||||
tempcount = tempcount + 1
|
||||
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
||||
local rad = 2.5 + (tempcount * 2)
|
||||
local Positions = self:_GetUnitPositions(randomcoord, rad, heading, _template)
|
||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template, alias)
|
||||
:InitDelayOff()
|
||||
:InitSetUnitAbsolutePositions(Positions)
|
||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
|
||||
:SpawnFromVec2(randomcoord:GetVec2())
|
||||
self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter], cType)
|
||||
end
|
||||
|
||||
foundCargo:SetWasDropped(true)
|
||||
if cType == CTLD_CARGO.Enum.ENGINEERS then
|
||||
self.Engineers = self.Engineers + 1
|
||||
local grpname = self.DroppedTroops[self.TroopCounter]:GetName()
|
||||
self.EngineersInField[self.Engineers] = CTLD_ENGINEERING:New(name, grpname)
|
||||
deployedEngineersByName[name] = (deployedEngineersByName[name] or 0) + 1
|
||||
else
|
||||
deployedTroopsByName[name] = (deployedTroopsByName[name] or 0) + 1
|
||||
end
|
||||
|
||||
table.remove(chunk, 1)
|
||||
if #chunk == 0 then
|
||||
self.TroopsIDToChunk[chunkID] = nil
|
||||
break
|
||||
end
|
||||
randomcoord:Translate(offset, Angle, nil, true)
|
||||
end
|
||||
|
||||
local tempcount = 0
|
||||
if isHook then
|
||||
tempcount = self.ChinookTroopCircleRadius or 5
|
||||
local parts = {}
|
||||
for nName,nCount in pairs(deployedTroopsByName) do
|
||||
parts[#parts + 1] = tostring(nCount).."x Troops "..nName
|
||||
end
|
||||
for _, _template in pairs(tmpl) do
|
||||
self.TroopCounter = self.TroopCounter + 1
|
||||
tempcount = tempcount + 1
|
||||
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
||||
local rad = 2.5 + (tempcount * 2)
|
||||
local Positions = self:_GetUnitPositions(randomcoord, rad, heading, _template)
|
||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template, alias)
|
||||
:InitDelayOff()
|
||||
:InitSetUnitAbsolutePositions(Positions)
|
||||
:InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits)
|
||||
:OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end)
|
||||
:SpawnFromVec2(randomcoord:GetVec2())
|
||||
self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter], cType)
|
||||
for nName,nCount in pairs(deployedEngineersByName) do
|
||||
parts[#parts + 1] = tostring(nCount).."x Engineers "..nName
|
||||
end
|
||||
|
||||
foundCargo:SetWasDropped(true)
|
||||
if cType == CTLD_CARGO.Enum.ENGINEERS then
|
||||
self.Engineers = self.Engineers + 1
|
||||
local grpname = self.DroppedTroops[self.TroopCounter]:GetName()
|
||||
self.EngineersInField[self.Engineers] = CTLD_ENGINEERING:New(name, grpname)
|
||||
self:_SendMessage(string.format("Dropped Engineers %s into action!", name), 10, false, Group)
|
||||
else
|
||||
self:_SendMessage(string.format("Dropped Troops %s into action!", name), 10, false, Group)
|
||||
if #parts > 0 then
|
||||
self:_SendMessage("Dropped "..table.concat(parts, ", ").." into action!", 10, false, Group)
|
||||
end
|
||||
|
||||
table.remove(chunk, 1)
|
||||
if #chunk == 0 then
|
||||
self.TroopsIDToChunk[chunkID] = nil
|
||||
end
|
||||
|
||||
else
|
||||
-- Return to base logic, remove ONLY the first cargo
|
||||
self:_SendMessage("Troops have returned to base!", 10, false, Group)
|
||||
@@ -6533,7 +6583,8 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID)
|
||||
|
||||
if self.TroopsIDToChunk and self.TroopsIDToChunk[chunkID] then
|
||||
local chunk = self.TroopsIDToChunk[chunkID]
|
||||
if #chunk > 0 then
|
||||
for n = 1, qty do
|
||||
if #chunk == 0 then break end
|
||||
local firstObj = chunk[1]
|
||||
local cName = firstObj:GetName()
|
||||
local gentroops = self.Cargo_Troops
|
||||
@@ -6548,9 +6599,9 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID)
|
||||
end
|
||||
firstObj:SetWasDropped(true)
|
||||
table.remove(chunk, 1)
|
||||
if #chunk == 0 then
|
||||
self.TroopsIDToChunk[chunkID] = nil
|
||||
end
|
||||
end
|
||||
if #chunk == 0 then
|
||||
self.TroopsIDToChunk[chunkID] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -6625,15 +6676,22 @@ function CTLD:_RefreshDropTroopsMenu(Group, Unit)
|
||||
for tName, objList in pairs(troopsByName) do
|
||||
table.sort(objList, function(a,b) return a:GetID() < b:GetID() end)
|
||||
local count = #objList
|
||||
if count > 0 then
|
||||
local chunkID = objList[1]:GetID()
|
||||
self.TroopsIDToChunk[chunkID] = objList
|
||||
|
||||
local chunkID = objList[1]:GetID()
|
||||
self.TroopsIDToChunk[chunkID] = objList
|
||||
|
||||
local label = string.format("Drop %s (%d)", tName, count)
|
||||
MENU_GROUP_COMMAND:New(theGroup, label, dropTroopsMenu, self._UnloadSingleTroopByID, self, theGroup, theUnit, chunkID)
|
||||
local label = string.format("Drop %s (%d)", tName, count)
|
||||
if count == 1 then
|
||||
MENU_GROUP_COMMAND:New(theGroup, label, dropTroopsMenu, self._UnloadSingleTroopByID, self, theGroup, theUnit, chunkID, 1)
|
||||
else
|
||||
local parentMenu = MENU_GROUP:New(theGroup, label, dropTroopsMenu)
|
||||
for q = 1, count do
|
||||
MENU_GROUP_COMMAND:New(theGroup, string.format("Drop (%d) %s", q, tName), parentMenu, self._UnloadSingleTroopByID, self, theGroup, theUnit, chunkID, q)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- [Internal] Function to check if a template exists in the mission.
|
||||
-- @param #CTLD self
|
||||
-- @param #table temptable Table of string names
|
||||
|
||||
Reference in New Issue
Block a user