From 3335429dfcd2ab3bb9b7ff4f7c4641c4f481d652 Mon Sep 17 00:00:00 2001 From: Ciaran Fisher Date: Sun, 1 Nov 2015 13:45:29 +0000 Subject: [PATCH] Added new Functions - Release 1.36 Added ctld.loadTransport Mission Editor Function Added ctld.countDroppedGroupsInZone(_zone, _blueFlag, _redFlag) Added ctld.countDroppedUnitsInZone(_zone, _blueFlag, _redFlag) --- CTLD.lua | 271 +++++++++++++++++++++++++--------------- Pickup-Dropoff-Demo.miz | Bin 480199 -> 482235 bytes README.md | 16 +++ test-mission.miz | Bin 493675 -> 494834 bytes 4 files changed, 188 insertions(+), 99 deletions(-) diff --git a/CTLD.lua b/CTLD.lua index 3d9fc77..e2b23e6 100644 --- a/CTLD.lua +++ b/CTLD.lua @@ -4,7 +4,7 @@ Allows Huey, Mi-8 and C130 to transport troops internally and Helicopters to transport Logistic / Vehicle units to the field via sling-loads without requiring external mods. - Supports some of the original CTTS functionality such as AI auto troop load and unload as well as group spawning and preloading of troops into units. + Supports all of the original CTTS functionality such as AI auto troop load and unload as well as group spawning and preloading of troops into units. Supports deployment of Auto Lasing JTAC to the field @@ -13,10 +13,9 @@ Contributors: - Steggles - https://github.com/Bob7heBuilder - Version: 1.35 - 27/10/2015 - Added ctld.unloadTransport Mission Editor Function - - Added flag option to the pickup zones - - Added ctld.changeRemainingGroupsForPickupZone Editor Function - - Added ability to use a SHIP as a pickup zone, just add the Ship UNIT NAME to the ctld.pickupZone list + Version: 1.36 -01/11/2015 - Added ctld.loadTransport Mission Editor Function + - Added ctld.countDroppedGroupsInZone(_zone, _blueFlag, _redFlag) + - Added ctld.countDroppedUnitsInZone(_zone, _blueFlag, _redFlag) ]] @@ -46,7 +45,7 @@ ctld.fastRopeMaximumHeight = 18.28 -- in meters which is 60 ft max fast rope (no ctld.vehiclesForTransportRED = { "BRDM-2", "BTR_D" } -- vehicles to load onto Il-76 - Alternatives {"Strela-1 9P31","BMP-1"} ctld.vehiclesForTransportBLUE = { "M1045 HMMWV TOW", "M1043 HMMWV Armament" } -- vehicles to load onto c130 - Alternatives {"M1128 Stryker MGS","M1097 Avenger"} -ctld.hawkLaunchers = 3 -- controls how many launchers to add to the hawk when its spawned. +ctld.hawkLaunchers = 3 -- controls how many launchers to add to the hawk/kub/buk when its spawned. ctld.spawnRPGWithCoalition = true --spawns a friendly RPG unit with Coalition forces ctld.spawnStinger = false -- spawns a stinger / igla soldier with a group of 6 or more soldiers! @@ -579,6 +578,107 @@ function ctld.createExtractZone(_zone, _flagNumber, _smoke) end end +-- CONTINUOUS TRIGGER FUNCTION +-- This function will count the current number of extractable RED and BLUE +-- GROUPS in a zone and store the values in two flags +-- A group is only counted as being in a zone when the leader of that group +-- is in the zone +-- Use: ctld.countDroppedGroupsInZone("Zone Name", flagBlue, flagRed) +function ctld.countDroppedGroupsInZone(_zone, _blueFlag, _redFlag) + + local _triggerZone = trigger.misc.getZone(_zone) -- trigger to use as reference position + + if _triggerZone == nil then + trigger.action.outText("CTLD.lua ERROR: Cant find zone called " .. _zone, 10) + return + end + + local _zonePos = mist.utils.zoneToVec3(_zone) + + local _redCount = 0; + local _blueCount = 0; + + local _allGroups = {ctld.droppedTroopsRED,ctld.droppedTroopsBLUE,ctld.droppedVehiclesRED,ctld.droppedVehiclesBLUE} + for _, _extractGroups in pairs(_allGroups) do + for _,_groupName in pairs(_extractGroups) do + local _groupUnits = ctld.getGroup(_groupName) + + if #_groupUnits > 0 then + local _zonePos = mist.utils.zoneToVec3(_zone) + local _dist = ctld.getDistance(_groupUnits[1]:getPoint(), _zonePos) + + if _dist <= _triggerZone.radius then + + if (_groupUnits[1]:getCoalition() == 1) then + _redCount = _redCount + 1; + else + _blueCount = _blueCount + 1; + end + end + end + end + end + --set flag stuff + trigger.action.setUserFlag(_blueFlag, _blueCount) + trigger.action.setUserFlag(_redFlag, _redCount) + + -- env.info("Groups in zone ".._blueCount.." ".._redCount) + +end + +-- CONTINUOUS TRIGGER FUNCTION +-- This function will count the current number of extractable RED and BLUE +-- UNITS in a zone and store the values in two flags + +-- Use: ctld.countDroppedUnitsInZone("Zone Name", flagBlue, flagRed) +function ctld.countDroppedUnitsInZone(_zone, _blueFlag, _redFlag) + + local _triggerZone = trigger.misc.getZone(_zone) -- trigger to use as reference position + + if _triggerZone == nil then + trigger.action.outText("CTLD.lua ERROR: Cant find zone called " .. _zone, 10) + return + end + + local _zonePos = mist.utils.zoneToVec3(_zone) + + local _redCount = 0; + local _blueCount = 0; + + local _allGroups = {ctld.droppedTroopsRED,ctld.droppedTroopsBLUE,ctld.droppedVehiclesRED,ctld.droppedVehiclesBLUE} + + for _, _extractGroups in pairs(_allGroups) do + for _,_groupName in pairs(_extractGroups) do + local _groupUnits = ctld.getGroup(_groupName) + + if #_groupUnits > 0 then + + local _zonePos = mist.utils.zoneToVec3(_zone) + for _,_unit in pairs(_groupUnits) do + local _dist = ctld.getDistance(_unit:getPoint(), _zonePos) + + if _dist <= _triggerZone.radius then + + if (_unit:getCoalition() == 1) then + _redCount = _redCount + 1; + else + _blueCount = _blueCount + 1; + end + end + end + end + end + end + + + --set flag stuff + trigger.action.setUserFlag(_blueFlag, _blueCount) + trigger.action.setUserFlag(_redFlag, _redCount) + + -- env.info("Units in zone ".._blueCount.." ".._redCount) +end + + -- Creates a radio beacon on a random UHF - VHF and HF/FM frequency for homing -- This WILL NOT WORK if you dont add beacon.ogg and beaconsilent.ogg to the mission!!! -- e.g. ctld.createRadioBeaconAtZone("beaconZone","red", 1440,"Waypoint 1") will create a beacon at trigger zone "beaconZone" for the Red side @@ -757,7 +857,7 @@ function ctld.unloadInProximityToEnemy(_unitName,_distance) if _nearestEnemy ~= nil then - if ctld.troopsOnboard(_unit, true) then + if ctld.troopsOnboard(_unit, true) then ctld.deployTroops(_unit, true) return true end @@ -784,16 +884,33 @@ function ctld.unloadTransport(_unitName) if _unit ~= nil then if ctld.troopsOnboard(_unit, true) then - ctld.deployTroops(_unit, true) + ctld.loadUnloadTroops({_unitName,true,"unload"}) end if ctld.unitCanCarryVehicles(_unit) and ctld.troopsOnboard(_unit, false) then - ctld.deployTroops(_unit, false) + ctld.loadUnloadTroops({_unitName,false,"unload"}) end end end +-- Loads Troops and Vehicles from a zone or picks up nearby troops or vehicles +function ctld.loadTransport(_unitName) + + local _unit = ctld.getTransportUnit(_unitName) + + if _unit ~= nil then + + ctld.loadUnloadTroops({_unitName,true,"load"}) + + if ctld.unitCanCarryVehicles(_unit) then + ctld.loadUnloadTroops({_unitName,false,"load"}) + end + + end + +end + -- *************************************************************** -- **************** BE CAREFUL BELOW HERE ************************ -- *************************************************************** @@ -1384,6 +1501,7 @@ function ctld.loadUnloadTroops(_args) local _heli = ctld.getTransportUnit(_args[1]) local _troops = _args[2] + local _mode = _args[3] or "" if _heli == nil then return @@ -1391,27 +1509,22 @@ function ctld.loadUnloadTroops(_args) local _zone = ctld.inPickupZone(_heli) - -- first check for extractable troops regardless of if we're in a zone or not - - if not ctld.troopsOnboard(_heli, _troops) then + if not ctld.troopsOnboard(_heli, _troops) and (_mode == "load" or _mode == "") then local _extract + -- first check for extractable troops regardless of if we're in a zone or not if _troops then if _heli:getCoalition() == 1 then - _extract = ctld.findNearestGroup(_heli, ctld.droppedTroopsRED) else - _extract = ctld.findNearestGroup(_heli, ctld.droppedTroopsBLUE) end else if _heli:getCoalition() == 1 then - _extract = ctld.findNearestGroup(_heli, ctld.droppedVehiclesRED) else - _extract = ctld.findNearestGroup(_heli, ctld.droppedVehiclesBLUE) end end @@ -1421,43 +1534,45 @@ function ctld.loadUnloadTroops(_args) ctld.extractTroops(_heli, _troops) return -- stop + elseif _zone.inZone == true then + + if _zone.limit - 1 >= 0 then + -- decrease zone counter by 1 + ctld.updateZoneCounter(_zone.index, -1) + + ctld.loadTroops(_heli, _troops) + else + ctld.displayMessageToGroup(_heli, "This area has no more reinforcements available!", 20) + end + + else + -- search for nearest troops to pickup + ctld.extractTroops(_heli, _troops) + end + + elseif ( _mode == "unload" or _mode == "") then -- dont unload if we just want to force loading + + -- troops must be onboard to get here + if _zone.inZone == true then + + if _troops then + ctld.displayMessageToGroup(_heli, "Dropped troops back to base", 20) + ctld.inTransitTroops[_heli:getName()].troops = nil + + else + ctld.displayMessageToGroup(_heli, "Dropped vehicles back to base", 20) + ctld.inTransitTroops[_heli:getName()].vehicles = nil + end + + -- increase zone counter by 1 + ctld.updateZoneCounter(_zone.index, 1) + + elseif _zone.inZone == false and ctld.troopsOnboard(_heli, _troops) then + + ctld.deployTroops(_heli, _troops) end end - if _zone.inZone == true and ctld.troopsOnboard(_heli, _troops) then - - if _troops then - ctld.displayMessageToGroup(_heli, "Dropped troops back to base", 20) - ctld.inTransitTroops[_heli:getName()].troops = nil - - else - ctld.displayMessageToGroup(_heli, "Dropped vehicles back to base", 20) - ctld.inTransitTroops[_heli:getName()].vehicles = nil - end - - -- increase zone counter by 1 - ctld.updateZoneCounter(_zone.index, 1) - - - elseif _zone.inZone == false and ctld.troopsOnboard(_heli, _troops) then - - ctld.deployTroops(_heli, _troops) - - elseif _zone.inZone == true and not ctld.troopsOnboard(_heli, _troops) then - - if _zone.limit - 1 >= 0 then - -- decrease zone counter by 1 - ctld.updateZoneCounter(_zone.index, -1) - - ctld.loadTroops(_heli, _troops) - else - ctld.displayMessageToGroup(_heli, "This area has no more reinforcements available!", 20) - end - - else - -- search for nearest troops to pickup - ctld.extractTroops(_heli, _troops) - end end function ctld.extractTroops(_heli, _troops) @@ -3532,70 +3647,28 @@ function ctld.checkAIStatus() local _unit = ctld.getTransportUnit(_unitName) + -- no player name means AI! if _unit ~= nil and _unit:getPlayerName() == nil then - - -- no player name means AI! local _zone = ctld.inPickupZone(_unit) + if _zone.inZone == true and not ctld.troopsOnboard(_unit, true) then - -- first check for extractable troop in the pickup zone - local _extract - - if _unit:getCoalition() == 1 then - _extract = ctld.findNearestGroup(_unit, ctld.droppedTroopsRED) - else - _extract = ctld.findNearestGroup(_unit, ctld.droppedTroopsBLUE) - end - - if _extract ~= nil then - -- search for nearest troops to pickup - ctld.extractTroops(_unit, true) - else - - --only allow if zone has units - if _zone.limit - 1 >= 0 then - - ctld.updateZoneCounter(_zone.index, -1) - - ctld.loadTroops(_unit, true) - end - end + ctld.loadUnloadTroops({_unitName,true,"load"}) elseif ctld.inDropoffZone(_unit) and ctld.troopsOnboard(_unit, true) then - ctld.deployTroops(_unit, true) + ctld.loadUnloadTroops({_unitName,true,"unload"}) end if ctld.unitCanCarryVehicles(_unit) then - local _zone = ctld.inPickupZone(_unit) if _zone.inZone == true and not ctld.troopsOnboard(_unit, false) then - -- first check for extractable vehicles in the pickup zone - local _extract - - if _unit:getCoalition() == 1 then - _extract = ctld.findNearestGroup(_unit, ctld.droppedVehiclesRED) - else - _extract = ctld.findNearestGroup(_unit, ctld.droppedVehiclesBLUE) - end - - if _extract ~= nil then - -- search for nearest vehicles to pickup - ctld.extractTroops(_unit, false) - else - --only allow if zone has units - if _zone.limit - 1 >= 0 then - - ctld.updateZoneCounter(_zone.index, -1) - - ctld.loadTroops(_unit, false) - end - end + ctld.loadUnloadTroops({_unitName,false,"load"}) elseif ctld.inDropoffZone(_unit) and ctld.troopsOnboard(_unit, false) then - ctld.deployTroops(_unit, false) + ctld.loadUnloadTroops({_unitName,false,"unload"}) end end end @@ -4262,7 +4335,7 @@ function ctld.getGroup(groupName) if _groupUnits ~= nil and #_groupUnits > 0 then for _x = 1, #_groupUnits do - if _groupUnits[_x]:getLife() > 0 and _groupUnits[_x]:isExist() then + if _groupUnits[_x]:getLife() > 0 then -- removed and _groupUnits[_x]:isExist() as isExist doesnt work on single units! table.insert(_filteredUnits, _groupUnits[_x]) end end diff --git a/Pickup-Dropoff-Demo.miz b/Pickup-Dropoff-Demo.miz index 5480bb3d121b306f002ec73b1cd64d327795656b..38fd6abe1c27d5e7a0661e1514d1a9cbf35f406d 100644 GIT binary patch delta 33349 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