Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Ben Birch
2021-08-22 12:54:25 +10:00
14 changed files with 278 additions and 152 deletions

View File

@@ -1,4 +1,3 @@
--- **Ops** -- Combat Search and Rescue.
--
-- ===
@@ -23,7 +22,7 @@
-- @module Ops.CSAR
-- @image OPS_CSAR.jpg
-- Date: July 2021
-- Date: Aug 2021
-------------------------------------------------------------------------
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
@@ -70,6 +69,7 @@
--
-- self.allowDownedPilotCAcontrol = false -- Set to false if you don\'t want to allow control by Combined Arms.
-- self.allowFARPRescue = true -- allows pilots to be rescued by landing at a FARP or Airbase. Else MASH only!
-- self.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued.
-- self.autosmoke = false -- automatically smoke a downed pilot\'s location when a heli is near.
-- self.autosmokedistance = 1000 -- distance for autosmoke
-- self.coordtype = 1 -- Use Lat/Long DDM (0), Lat/Long DMS (1), MGRS (2), Bullseye imperial (3) or Bullseye metric (4) for coordinates.
@@ -95,6 +95,8 @@
-- self.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters
-- self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters
-- self.pilotmustopendoors = false -- switch to true to enable check of open doors
-- -- (added 0.1.9)
-- self.suppressmessages = false -- switch off all messaging if you want to do your own
--
-- ## 2.1 Experimental Features
--
@@ -214,26 +216,6 @@ CSAR = {
-- @field Wrapper.Group#GROUP group Spawned group object.
-- @field #number timestamp Timestamp for approach process
-- @field #boolean alive Group is alive or dead/rescued
--
--- Updated and sorted list of known NDB beacons (in kHz!) from the available maps.
--[[ Moved to Utils
-- @field #CSAR.SkipFrequencies
CSAR.SkipFrequencies = {
214,274,291.5,295,297.5,
300.5,304,307,309.5,311,312,312.5,316,
320,324,328,329,330,336,337,
342,343,348,351,352,353,358,
363,365,368,372.5,374,
380,381,384,389,395,396,
414,420,430,432,435,440,450,455,462,470,485,
507,515,520,525,528,540,550,560,570,577,580,602,625,641,662,670,680,682,690,
705,720,722,730,735,740,745,750,770,795,
822,830,862,866,
905,907,920,935,942,950,995,
1000,1025,1030,1050,1065,1116,1175,1182,1210
}
--]]
--- All slot / Limit settings
-- @type CSAR.AircraftType
@@ -251,7 +233,7 @@ CSAR.AircraftType["Mi-24V"] = 8
--- CSAR class version.
-- @field #string version
CSAR.version="0.1.8r3"
CSAR.version="0.1.10r3"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
@@ -361,12 +343,13 @@ function CSAR:New(Coalition, Template, Alias)
self.loadtimemax = 135 -- seconds
self.radioSound = "beacon.ogg" -- the name of the sound file to use for the Pilot radio beacons. If this isnt added to the mission BEACONS WONT WORK!
self.allowFARPRescue = true --allows pilot to be rescued by landing at a FARP or Airbase
self.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued.
self.max_units = 6 --max number of pilots that can be carried
self.useprefix = true -- Use the Prefixed defined below, Requires Unit have the Prefix defined below
self.csarPrefix = { "helicargo", "MEDEVAC"} -- prefixes used for useprefix=true - DON\'T use # in names!
self.template = Template or "generic" -- template for downed pilot
self.mashprefix = {"MASH"} -- prefixes used to find MASHes
self.mash = SET_GROUP:New():FilterCoalitions(self.coalition):FilterPrefixes(self.mashprefix):FilterOnce() -- currently only GROUP objects, maybe support STATICs also?
self.autosmoke = false -- automatically smoke location when heli is near
self.autosmokedistance = 2000 -- distance for autosmoke
-- added 0.1.4
@@ -378,6 +361,7 @@ function CSAR:New(Coalition, Template, Alias)
self.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters
self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters
self.pilotmustopendoors = false -- switch to true to enable check on open doors
self.suppressmessages = false
-- WARNING - here\'ll be dragons
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
@@ -642,7 +626,7 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
local _typeName = _typeName or "Pilot"
if not noMessage then
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _typeName .. " is down. ", self.coalition, 10)
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _typeName .. " is down. ", self.coalition, self.messageTime)
end
if _freq then
@@ -806,8 +790,7 @@ function CSAR:_EventHandler(EventData)
if self:_DoubleEjection(_unitname) then
return
end
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _unit:GetTypeName() .. " shot down. No Chute!", self.coalition, 10)
--local m = MESSAGE:New("MAYDAY MAYDAY! " .. _unit:GetTypeName() .. " shot down. No Chute!",10,"Info"):ToCoalition(self.coalition)
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _unit:GetTypeName() .. " shot down. No Chute!", self.coalition, self.messageTime)
else
self:T(self.lid .. " Pilot has not taken off, ignore")
end
@@ -894,11 +877,14 @@ function CSAR:_EventHandler(EventData)
end
if _place:GetCoalition() == self.coalition or _place:GetCoalition() == coalition.side.NEUTRAL then
self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true)
--[[
if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_event.IniUnitName) then
self:_DisplayMessageToSAR(_unit, "Open the door to let me out!", self.messageTime, true)
else
self:_RescuePilots(_unit)
end
--]]
else
self:T(string.format("Airfield %d, Unit %d", _place:GetCoalition(), _unit:GetCoalition()))
end
@@ -934,7 +920,7 @@ function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage)
end
-- trigger FSM event
self:__PilotDown(2,_downedGroup, _freqk, _leadername, _coordinatesText)
self:__PilotDown(2,_downedGroup, _freqk, _groupName, _coordinatesText)
return self
end
@@ -1112,7 +1098,7 @@ function CSAR:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupNam
player = grouptable.player,
}
_woundedGroup:Destroy()
_woundedGroup:Destroy(false)
self:_RemoveNameFromDownedPilots(_woundedGroupName,true)
self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s I\'m in! Get to the MASH ASAP! ", _heliName, _pilotName), self.messageTime,true,true)
@@ -1143,6 +1129,8 @@ end
-- @return #boolean outcome The outcome.
function CSAR:_IsLoadingDoorOpen( unit_name )
self:T(self.lid .. " _IsLoadingDoorOpen")
--[[
local ret_val = false
local unit = Unit.getByName(unit_name)
if unit ~= nil then
@@ -1174,8 +1162,9 @@ function CSAR:_IsLoadingDoorOpen( unit_name )
return ret_val
end -- nil
--]]
return UTILS.IsLoadingDoorOpen(unit_name)
return false
end
--- (Internal) Function to check if heli is close to group.
@@ -1314,7 +1303,8 @@ end
-- @param #CSAR self
-- @param #string heliname Heli name
-- @param #string groupname Group name
function CSAR:_ScheduledSARFlight(heliname,groupname)
-- @param #boolean isairport If true, EVENT.Landing took place at an airport or FARP
function CSAR:_ScheduledSARFlight(heliname,groupname, isairport)
self:T(self.lid .. " _ScheduledSARFlight")
self:T({heliname,groupname})
local _heliUnit = self:_GetSARHeli(heliname)
@@ -1337,8 +1327,8 @@ function CSAR:_ScheduledSARFlight(heliname,groupname)
return
end
if _dist < 200 and _heliUnit:InAir() == false then
if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(heliname) then
if ( _dist < self.FARPRescueDistance or isairport ) and _heliUnit:InAir() == false then
if self.pilotmustopendoors and self:_IsLoadingDoorOpen(heliname) == false then
self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me out!", self.messageTime, true)
else
self:_RescuePilots(_heliUnit)
@@ -1347,7 +1337,7 @@ function CSAR:_ScheduledSARFlight(heliname,groupname)
end
--queue up
self:__Returning(-5,heliname,_woundedGroupName)
self:__Returning(-5,heliname,_woundedGroupName, isairport)
return self
end
@@ -1403,7 +1393,9 @@ function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak)
local group = _unit:GetGroup()
local _clear = _clear or nil
local _time = _time or self.messageTime
local m = MESSAGE:New(_text,_time,"Info",_clear):ToGroup(group)
if not self.suppressmessages then
local m = MESSAGE:New(_text,_time,"Info",_clear):ToGroup(group)
end
-- integrate SRS
if _speak and self.useSRS then
local srstext = SOUNDTEXT:New(_text)
@@ -1501,10 +1493,17 @@ function CSAR:_GetClosestDownedPilot(_heli)
local _shortestDistance = -1
local _distance = 0
local _closestGroupInfo = nil
local _heliCoord = _heli:GetCoordinate()
local _heliCoord = _heli:GetCoordinate() or _heli:GetCoordinate()
if _heliCoord == nil then
self:E("****Error obtaining coordinate!")
return nil
end
local DownedPilotsTable = self.downedPilots
for _, _groupInfo in pairs(DownedPilotsTable) do
for _, _groupInfo in UTILS.spairs(DownedPilotsTable) do
--for _, _groupInfo in pairs(DownedPilotsTable) do
local _woundedName = _groupInfo.name
local _tempWounded = _groupInfo.group
@@ -1570,12 +1569,11 @@ end
-- @param #number _messagetime How long to show.
function CSAR:_DisplayToAllSAR(_message, _side, _messagetime)
self:T(self.lid .. " _DisplayToAllSAR")
local messagetime = _messagetime or self.messageTime
for _, _unitName in pairs(self.csarUnits) do
local _unit = self:_GetSARHeli(_unitName)
if _unit then
if not _messagetime then
self:_DisplayMessageToSAR(_unit, _message, _messagetime)
end
if _unit and not self.suppressmessages then
self:_DisplayMessageToSAR(_unit, _message, _messagetime)
end
end
return self
@@ -1747,9 +1745,21 @@ end
function CSAR:_GetDistance(_point1, _point2)
self:T(self.lid .. " _GetDistance")
if _point1 and _point2 then
local distance = _point1:DistanceFromPointVec2(_point2)
return distance
local distance1 = _point1:Get2DDistance(_point2)
local distance2 = _point1:DistanceFromPointVec2(_point2)
self:I({dist1=distance1, dist2=distance2})
if distance1 and type(distance1) == "number" then
return distance1
elseif distance2 and type(distance2) == "number" then
return distance2
else
self:E("*****Cannot calculate distance!")
self:E({_point1,_point2})
return -1
end
else
self:E("******Cannot calculate distance!")
self:E({_point1,_point2})
return -1
end
end
@@ -1907,6 +1917,7 @@ function CSAR:onafterStart(From, Event, To)
else
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart()
end
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also?
self:__Status(-10)
return self
end
@@ -1915,19 +1926,19 @@ end
-- @param #CSAR self
function CSAR:_CheckDownedPilotTable()
local pilots = self.downedPilots
for _,_entry in pairs (pilots) do
self:T("Checking for " .. _entry.name)
self:T({entry=_entry})
local group = _entry.group
if not group:IsAlive() then
self:T("Group is dead")
if _entry.alive == true then
self:T("Switching .alive to false")
local npilots = {}
for _ind,_entry in pairs(pilots) do
local _group = _entry.group
if _group:IsAlive() then
npilots[_ind] = _entry
else
if _entry.alive then
self:__KIA(1,_entry.desc)
self:_RemoveNameFromDownedPilots(_entry.name,true)
end
end
end
self.downedPilots = npilots
return self
end
@@ -2047,9 +2058,10 @@ end
-- @param #string To To state.
-- @param #string Heliname Name of the helicopter group.
-- @param #string Woundedgroupname Name of the downed pilot\'s group.
function CSAR:onbeforeReturning(From, Event, To, Heliname, Woundedgroupname)
-- @param #boolean IsAirport True if heli has landed on an AFB (from event land).
function CSAR:onbeforeReturning(From, Event, To, Heliname, Woundedgroupname, IsAirPort)
self:T({From, Event, To, Heliname, Woundedgroupname})
self:_ScheduledSARFlight(Heliname,Woundedgroupname)
self:_ScheduledSARFlight(Heliname,Woundedgroupname, IsAirPort)
return self
end

View File

@@ -22,7 +22,7 @@
-- @module Ops.CTLD
-- @image OPS_CTLD.jpg
-- Date: July 2021
-- Date: Aug 2021
do
------------------------------------------------------
@@ -264,7 +264,7 @@ do
-- Add zones for loading troops and crates and dropping, building crates
--
-- -- Add a zone of type LOAD to our setup. Players can load troops and crates.
-- -- "Loadzone" is the name of the zone from the ME. Players can load, if they are inside of the zone.
-- -- "Loadzone" is the name of the zone from the ME. Players can load, if they are inside the zone.
-- -- Smoke and Flare color for this zone is blue, it is active (can be used) and has a radio beacon.
-- my_ctld:AddCTLDZone("Loadzone",CTLD.CargoZoneType.LOAD,SMOKECOLOR.Blue,true,true)
--
@@ -279,6 +279,13 @@ do
--
-- my_ctld:AddCTLDZone("Movezone2",CTLD.CargoZoneType.MOVE,SMOKECOLOR.White,true,true)
--
-- -- Add a zone of type SHIP to our setup. Players can load troops and crates from this ship
-- -- "Tarawa" is the unitname (callsign) of the ship from the ME. Players can load, if they are inside the zone.
-- -- The ship is 240 meters long and 20 meters wide.
-- -- Note that smoke, flares, beacons don't work for this type of loadzone (yet). Also, you need to adjust
-- -- the max hover height to deck height plus 5 meters or so for loading to work.
-- -- When the ship is moving, forcing hoverload might not be a good idea.
-- my_ctld:AddCTLDZone("Tarawa",CTLD.CargoZoneType.SHIP,SMOKECOLOR.Blue,true,true,240,20)
--
-- ## 2. Options
--
@@ -511,11 +518,13 @@ CTLD = {
-- @field #string name Name of Zone.
-- @field #string color Smoke color for zone, e.g. SMOKECOLOR.Red.
-- @field #boolean active Active or not.
-- @field #string type Type of zone, i.e. load,drop,move
-- @field #string type Type of zone, i.e. load,drop,move,ship
-- @field #boolean hasbeacon Create and run radio beacons if active.
-- @field #table fmbeacon Beacon info as #CTLD.ZoneBeacon
-- @field #table uhfbeacon Beacon info as #CTLD.ZoneBeacon
-- @field #table vhfbeacon Beacon info as #CTLD.ZoneBeacon
-- @field #number shiplength For ships - length of ship
-- @field #number shipwidth For ships - width of ship
--- Zone Type Info.
-- @type CTLD.CargoZoneType
@@ -523,6 +532,7 @@ CTLD.CargoZoneType = {
LOAD = "load",
DROP = "drop",
MOVE = "move",
SHIP = "ship",
}
--- Buildable table info.
@@ -557,7 +567,7 @@ CTLD.UnitTypes = {
--- CTLD class version.
-- @field #string version
CTLD.version="0.1.4r3"
CTLD.version="0.1.5a1"
--- Instantiate a new CTLD.
-- @param #CTLD self
@@ -643,6 +653,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
self.pickupZones = {}
self.dropOffZones = {}
self.wpZones = {}
self.shipZones = {}
-- Cargo
self.Cargo_Crates = {}
@@ -659,6 +670,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
-- setup
self.CrateDistance = 30 -- list/load crates in this radius
self.ExtractFactor = 3.33 -- factor for troops extraction, i.e. CrateDistance * Extractfactor
self.prefixes = Prefixes or {"Cargoheli"}
--self.I({prefixes = self.prefixes})
self.useprefix = true
@@ -927,6 +939,9 @@ function CTLD:_LoadTroops(Group, Unit, Cargotype)
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
@@ -1116,8 +1131,10 @@ end
nearestDistance = distance
end
end
if nearestGroup == nil or nearestDistance > self.CrateDistance then
local extractdistance = self.CrateDistance * self.ExtractFactor
if nearestGroup == nil or nearestDistance > extractdistance then
self:_SendMessage("No units close enough to extract!", 10, false, Group)
return self
end
@@ -1165,7 +1182,7 @@ end
-- clean up:
table.remove(self.DroppedTroops, nearestGroupIndex)
nearestGroup:Destroy()
nearestGroup:Destroy(false)
end
return self
end
@@ -1183,8 +1200,13 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop)
-- check if we are in LOAD zone
local inzone = false
local drop = drop or false
local ship = nil
local width = 20
if not drop then
inzone = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
if not inzone then
inzone, ship, zone, distance, width = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
end
else
if self.dropcratesanywhere then -- #1570
inzone = true
@@ -1230,18 +1252,33 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop)
for i=1,50 do
math.random(90,270)
end
local rheading = math.floor(math.random(90,270) * heading + 1 / 360)
local rheading = math.floor(((math.random(90,270) * heading) + 1) / 360)
if not IsHerc then
rheading = rheading + 180 -- mirror for Helis
end
if rheading > 360 then rheading = rheading - 360 end -- catch > 360
local cratecoord = position:Translate(cratedistance,rheading)
local cratevec2 = cratecoord:GetVec2()
self.CrateCounter = self.CrateCounter + 1
self.CrateCounter = self.CrateCounter + 1
if type(ship) == "string" then
self:T("Spawning on ship "..ship)
local Ship = UNIT:FindByName(ship)
local shipcoord = Ship:GetCoordinate()
local unitcoord = Unit:GetCoordinate()
local dist = shipcoord:Get2DDistance(unitcoord)
dist = dist - (20 + math.random(1,10))
local width = width / 2
local Offy = math.random(-width,width)
self.Spawned_Crates[self.CrateCounter] = SPAWNSTATIC:NewFromType("container_cargo","Cargos",country.id.GERMANY)
--:InitCoordinate(cratecoord)
:InitLinkToUnit(Ship,dist,Offy,0)
:Spawn(270,cratealias)
else
self.Spawned_Crates[self.CrateCounter] = SPAWNSTATIC:NewFromType("container_cargo","Cargos",country.id.GERMANY)
:InitCoordinate(cratecoord)
--:InitLinkToUnit(Unit,OffsetX,OffsetY,OffsetAngle)
:Spawn(270,cratealias)
end
local templ = cargotype:GetTemplates()
local sorte = cargotype:GetType()
self.CargoCounter = self.CargoCounter +1
@@ -1390,8 +1427,13 @@ function CTLD:_LoadCratesNearby(Group, Unit)
-- get nearby crates
local finddist = self.CrateDistance or 30
local nearcrates,number = self:_FindCratesNearby(Group,Unit,finddist) -- #table
if number == 0 or numberonboard == cratelimit then
self:_SendMessage("Sorry no loadable crates nearby or fully loaded!", 10, false, Group)
if number == 0 and self.hoverautoloading then
return -- exit
elseif number == 0 then
self:_SendMessage("Sorry no loadable crates nearby!", 10, false, Group)
return -- exit
elseif numberonboard == cratelimit then
self:_SendMessage("Sorry no fully loaded!", 10, false, Group)
return -- exit
else
-- go through crates and load
@@ -1415,7 +1457,7 @@ function CTLD:_LoadCratesNearby(Group, Unit)
table.insert(loaded.Cargo, crate)
table.insert(crateidsloaded,crate:GetID())
-- destroy crate
crate:GetPositionable():Destroy()
crate:GetPositionable():Destroy(false)
crate.Positionable = nil
self:_SendMessage(string.format("Crate ID %d for %s loaded!",crate:GetID(),crate:GetName()), 10, false, Group)
self:__CratesPickedUp(1, Group, Unit, crate)
@@ -1474,9 +1516,10 @@ function CTLD:_UpdateUnitCargoMass(Unit)
self:T(self.lid .. " _UpdateUnitCargoMass")
local calculatedMass = self:_GetUnitCargoMass(Unit)
Unit:SetUnitInternalCargo(calculatedMass)
local report = REPORT:New("Loadmaster report")
report:Add("Carrying " .. calculatedMass .. "Kg")
self:_SendMessage(report:Text(),10,false,Unit:GetGroup())
--local report = REPORT:New("Loadmaster report")
--report:Add("Carrying " .. calculatedMass .. "Kg")
--self:_SendMessage(report:Text(),10,false,Unit:GetGroup())
return self
end
--- (Internal) Function to list loaded cargo.
@@ -1557,6 +1600,9 @@ function CTLD:_UnloadTroops(Group, Unit)
-- check if we are in LOAD zone
local droppingatbase = false
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 inzone then
droppingatbase = true
end
@@ -1966,7 +2012,7 @@ function CTLD:_CleanUpCrates(Crates,Build,Number)
if name == nametype then -- matching crate type
table.insert(destIDs,thisID)
found = found + 1
nowcrate:GetPositionable():Destroy()
nowcrate:GetPositionable():Destroy(false)
nowcrate.Positionable = nil
end
if found == numberdest then break end -- got enough
@@ -2132,6 +2178,8 @@ function CTLD:AddZone(Zone)
table.insert(self.pickupZones,zone)
elseif zone.type == CTLD.CargoZoneType.DROP then
table.insert(self.dropOffZones,zone)
elseif zone.type == CTLD.CargoZoneType.SHIP then
table.insert(self.shipZones,zone)
else
table.insert(self.wpZones,zone)
end
@@ -2157,6 +2205,8 @@ function CTLD:ActivateZone(Name,ZoneType,NewState)
table = self.pickupZones
elseif ZoneType == CTLD.CargoZoneType.DROP then
table = self.dropOffZones
elseif ZoneType == CTLD.CargoZoneType.SHIP then
table = self.shipZones
else
table = self.wpZones
end
@@ -2254,8 +2304,10 @@ end
-- @param #number Color Smoke/Flare color e.g. #SMOKECOLOR.Red
-- @param #string Active Is this zone currently active?
-- @param #string HasBeacon Does this zone have a beacon if it is active?
-- @param #number Shiplength Length of Ship for shipzones
-- @param #number Shipwidth Width of Ship for shipzones
-- @return #CTLD self
function CTLD:AddCTLDZone(Name, Type, Color, Active, HasBeacon)
function CTLD:AddCTLDZone(Name, Type, Color, Active, HasBeacon, Shiplength, Shipwidth)
self:T(self.lid .. " AddCTLDZone")
local ctldzone = {} -- #CTLD.CargoZone
@@ -2275,6 +2327,11 @@ function CTLD:AddCTLDZone(Name, Type, Color, Active, HasBeacon)
ctldzone.vhfbeacon = nil
end
if Type == CTLD.CargoZoneType.SHIP then
ctldzone.shiplength = Shiplength or 100
ctldzone.shipwidth = Shipwidth or 10
end
self:AddZone(ctldzone)
return self
end
@@ -2366,10 +2423,12 @@ end
-- @param #CTLD.CargoZoneType Zonetype Zonetype
-- @return #boolean Outcome Is in zone or not
-- @return #string name Closest zone name
-- @return #string zone Closest Core.Zone#ZONE object
-- @return Core.Zone#ZONE zone Closest Core.Zone#ZONE object
-- @return #number distance Distance to closest zone
-- @return #number width Radius of zone or width of ship
function CTLD:IsUnitInZone(Unit,Zonetype)
self:T(self.lid .. " IsUnitInZone")
self:T(Zonetype)
local unitname = Unit:GetName()
local zonetable = {}
local outcome = false
@@ -2377,6 +2436,8 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
zonetable = self.pickupZones -- #table
elseif Zonetype == CTLD.CargoZoneType.DROP then
zonetable = self.dropOffZones -- #table
elseif Zonetype == CTLD.CargoZoneType.SHIP then
zonetable = self.shipZones -- #table
else
zonetable = self.wpZones -- #table
end
@@ -2385,16 +2446,29 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
local colorret = nil
local maxdist = 1000000 -- 100km
local zoneret = nil
local zonewret = nil
local zonenameret = nil
for _,_cargozone in pairs(zonetable) do
local czone = _cargozone -- #CTLD.CargoZone
local unitcoord = Unit:GetCoordinate()
local zonename = czone.name
local zone = ZONE:FindByName(zonename)
zonecoord = zone:GetCoordinate()
local active = czone.active
local color = czone.color
local zoneradius = zone:GetRadius()
local zone = nil
local zoneradius = 100
local zonewidth = 20
if Zonetype == CTLD.CargoZoneType.SHIP then
self:T("Checking Type Ship: "..zonename)
zone = UNIT:FindByName(zonename)
zonecoord = zone:GetCoordinate()
zoneradius = czone.shiplength
zonewidth = czone.shipwidth
else
zone = ZONE:FindByName(zonename)
zonecoord = zone:GetCoordinate()
zoneradius = zone:GetRadius()
zonewidth = zoneradius
end
local distance = self:_GetDistance(zonecoord,unitcoord)
if distance <= zoneradius and active then
outcome = true
@@ -2403,10 +2477,15 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
maxdist = distance
zoneret = zone
zonenameret = zonename
zonewret = zonewidth
colorret = color
end
end
return outcome, zonenameret, zoneret, maxdist
if Zonetype == CTLD.CargoZoneType.SHIP then
return outcome, zonenameret, zoneret, maxdist, zonewret
else
return outcome, zonenameret, zoneret, maxdist
end
end
--- User function - Start smoke in a zone close to the Unit.
@@ -2589,6 +2668,9 @@ end
self:T(self.lid .. " CanHoverLoad")
if self:IsHercules(Unit) then return false end
local outcome = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD) and self:IsCorrectHover(Unit)
if not outcome then
outcome = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP) --and self:IsCorrectHover(Unit)
end
return outcome
end
@@ -2650,7 +2732,7 @@ end
if self.hoverautoloading then
for _,_pilot in pairs (self.CtldUnits) do
local Unit = UNIT:FindByName(_pilot)
self:AutoHoverLoad(Unit)
if self:CanHoverLoad(Unit) then self:AutoHoverLoad(Unit) end
end
end
return self
@@ -2682,7 +2764,7 @@ end
-- @return #CTLD self
function CTLD:onafterStart(From, Event, To)
self:T({From, Event, To})
self:I(self.lid .. "Started.")
self:I(self.lid .. "Started ("..self.version..")")
if self.useprefix or self.enableHercules then
local prefix = self.prefixes
if self.enableHercules then