diff --git a/CTLD.lua b/CTLD.lua index 19b3d74..adbd8e1 100644 --- a/CTLD.lua +++ b/CTLD.lua @@ -1,4 +1,5 @@ ---[[ +--[[ ! IMPORTANT : You must must use the version of MIST supplied in the CTLD pack to correctly manage dynamic spwans + Combat Troop and Logistics Drop Allows Huey, Mi-8 and C130 to transport troops internally and Helicopters to transport Logistic / Vehicle units to the field via sling-loads @@ -40,7 +41,7 @@ end ctld.Id = "CTLD - " --- Version. -ctld.Version = "1.5.2" +ctld.Version = "1.5.3" -- To add debugging messages to dcs.log, change the following log levels to `true`; `Debug` is less detailed than `Trace` ctld.Debug = false @@ -817,7 +818,9 @@ ctld.vehicleTransportEnabled = { -- We will also use this to make modifications to the menu and other checks and messages ctld.dynamicCargoUnits = { "CH-47Fbl1", - --"UH-1H", + "UH-1H", + "Mi-8MT", + "Mi-24P", } -- ************** Maximum Units SETUP for UNITS ****************** @@ -2618,10 +2621,19 @@ function ctld.spawnCrate(_arguments, bypassCrateWaitTime) -- add to move table ctld.crateMove[_name] = _name + + local refPoint = _heli:getPoint() + local refLat, refLon = coord.LOtoLL(refPoint) + local unitPos = _heli:getPosition() + local refHeading = math.deg(math.atan2(unitPos.x.z, unitPos.x.x)) + + local destLat, destLon, destAlt = coord.LOtoLL(_point) + local relativePos, forma = ctld.tools.getRelativeBearing(refLat, refLon, refHeading, destLat, destLon, 'clock') + ctld.displayMessageToGroup(_heli, ctld.i18n_translate("A %1 crate weighing %2 kg has been brought out and is at your %3 o'clock ", - _crateType.desc, _crateType.weight, _position), 20) + _crateType.desc, _crateType.weight, relativePos), 20) else env.info("Couldn't find crate item to spawn") end @@ -4224,8 +4236,7 @@ function ctld.dropSlingCrate(_args) _position = "6" end ctld.displayMessageToGroup(_heli, - ctld.i18n_translate("%1 crate has been safely unhooked and is at your %2 o'clock", _crate.desc, - _position), 10) + ctld.i18n_translate("%1 crate has been safely unhooked and is at your %2 o'clock", _crate.desc, _position), 10) elseif _heightDiff > 7.5 and _heightDiff <= 40.0 then ctld.displayMessageToGroup(_heli, ctld.i18n_translate("%1 crate has been safely dropped below you", _crate.desc), 10) @@ -5747,7 +5758,7 @@ function ctld.unitDynamicCargoCapable(_unit) --ctld.logDebug("ctld.unitDynamicCargoCapable(_type=[%s])", ctld.p(_type)) for _, _name in ipairs(ctld.dynamicCargoUnits) do local _nameLower = string.lower(_name) - if string.find(_type, _nameLower, 1, true) then --string.match does not work with patterns containing '-' as it is a magic character + if string.find(_type, _nameLower, 1, true) then --string.match does not work with patterns containing '-' as it is a magic character result = true break end @@ -8541,7 +8552,7 @@ function ctld.eventHandler:onEvent(event) for _, aircraftType in pairs(ctld.aircraftTypeTable) do if aircraftType == playerTypeName then ctld.logTrace("adding by aircraft type, unitName = %s", ctld.p(unitName)) - if ctld.isValueInIpairTable(ctld.transportPilotNames, unitName) == false then + if ctld.tools.isValueInIpairTable(ctld.transportPilotNames, unitName) == false then table.insert(ctld.transportPilotNames, unitName) -- add transport unit to the list end if ctld.addedTo[tostring(_groupId)] == nil then -- only if menu not already set up @@ -8619,7 +8630,8 @@ function ctld.RandomReal(mini, maxi) end -- Tools -function ctld.isValueInIpairTable(tab, value) +ctld.tools = {} +function ctld.tools.isValueInIpairTable(tab, value) for i, v in ipairs(tab) do if v == value then return true -- La valeur existe @@ -8627,6 +8639,58 @@ function ctld.isValueInIpairTable(tab, value) end return false -- La valeur n'existe pas end +------------------------------------------------------------------------------------ +--- Calculates the orientation of an end point relative to a reference point. +--- The calculation takes into account the current orientation of the reference point. +--- +--- @param refLat number Latitude of the reference point in degrees. +--- @param refLon number Longitude of the reference point in degrees. +--- @param refHeading number Current orientation of the reference point in degrees (0 = North, 90 = East). +--- @param destLat number Latitude of the arrival point in degrees. +--- @param destLon number Longitude of the arrival point in degrees. +--- @param resultFormat string The desired output format: "radian", "degree" or "clock". +--- @return number The relative orientation in the specified resultFormat. +function ctld.tools.getRelativeBearing(refLat, refLon, refHeading, destLat, destLon, resultFormat) + -- Converting degrees to radians for geometric calculations + local radrefLat = math.rad(refLat) + local raddestLat = math.rad(destLat) + local radrefLon = math.rad(refLon) + local raddestLon = math.rad(destLon) + local radrefHeading = math.rad(refHeading) + + -- Calculating the longitude difference between the two points + local deltaLon = raddestLon - radrefLon + + -- Using the great circle formula for azimuth (bearing) + -- This formula is based on spherical trigonometry and uses atan2 + -- to correctly handle all quadrants. + local y = math.sin(deltaLon) * math.cos(raddestLat) + local x = math.cos(radrefLat) * math.sin(raddestLat) - math.sin(radrefLat) * math.cos(raddestLat) * math.cos(deltaLon) + local absoluteBearingRad = math.atan2(y, x) + + -- Calculate relative orientation by subtracting the reference refHeading + local relativeBearingRad = absoluteBearingRad - radrefHeading + + -- Normalizes the angle to be in the range [-pi, pi] + -- This ensures a consistent angle, whether positive or negative. + local normalizedRad = (relativeBearingRad + math.pi) % (2 * math.pi) - math.pi + + -- Returns the value in the requested resultFormat + if resultFormat == "radian" then + return normalizedRad, resultFormat + elseif resultFormat == "clock" then + -- Convert to clock position (12h = front, 3h = right, 6h = back, etc..) + local bearingDeg = math.deg(normalizedRad) + local clockPosition = ((bearingDeg + 360) % 360) / 30 + clockPosition = clockPosition >= 0 and math.floor(clockPosition + 0.5) or math.ceil(clockPosition - 0.5), resultFormat -- rounded clockPosition + if clockPosition == 0 then clockPosition = 12 end + return clockPosition, resultFormat + else -- By default, the resultFormat is "degree" + resultFormat = "degree" + local bearingDeg = math.deg(normalizedRad) + return (bearingDeg + 360) % 360, resultFormat + end +end --- Enable/Disable error boxes displayed on screen. env.setErrorMessageBoxEnabled(false) diff --git a/README.md b/README.md index c3af9f2..2d26d3d 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ Optionaly, you can disable the STTS (text to speech over SRS) feature (4). ![dynamic_loading] ### Script Setup -**This script requires MIST version 4.0.57 or above: https://github.com/mrSkortch/MissionScriptingTools** +🔴IMPORTANT: This script requires MIST supplied in the CTLD zipped pack to correctly manage dynamic spwans. First make sure MIST is loaded, either as an Initialization Script for the mission or the first DO SCRIPT with a "TIME MORE" of 1. "TIME MORE" means run the actions after X seconds into the mission. diff --git a/mist.lua b/mist.lua index d5a07df..9618e7e 100644 --- a/mist.lua +++ b/mist.lua @@ -35,7 +35,7 @@ mist = {} -- don't change these mist.majorVersion = 4 mist.minorVersion = 5 -mist.build = "128-DYNSLOTS-01" +mist.build = "128-DYNSLOTS-02" -- forward declaration of log shorthand local log @@ -826,11 +826,11 @@ do -- the main scope if zone.verticies then local offset = {} for i = 1, #zone.verticies do - table.insert(offset, {dist = mist.utils.get2DDist(uRef.point, zone.verticies[i]), heading = mist.getHeadingPoints(uRef.point, zone.verticies[i]) + uRef.heading}) + table.insert(offset, {dist = mist.utils.get2DDist(uRef.point, zone.verticies[i]), heading = mist.utils.getHeadingPoints(uRef.point, zone.verticies[i]) + uRef.heading}) end zone.offset = offset else - zone.offset = {dist = mist.utils.get2DDist(uRef.point, zone.point), heading = mist.getHeadingPoints(uRef.point, zone.point) + uRef.heading} + zone.offset = {dist = mist.utils.get2DDist(uRef.point, zone.point), heading = mist.utils.getHeadingPoints(uRef.point, zone.point) + uRef.heading} end end end