cfxHeloTroops = {} cfxHeloTroops.version = "2.1.0" cfxHeloTroops.verbose = false cfxHeloTroops.autoDrop = true cfxHeloTroops.autoPickup = false cfxHeloTroops.pickupRange = 100 -- meters -- -- -- VERSION HISTORY -- 1.1.3 -- repaired forgetting 'wait-' when loading/disembarking -- 1.1.4 -- corrected coalition bug in deployTroopsFromHelicopter -- 2.0.0 -- added weight change when troops enter and leave the helicopter -- idividual troop capa max per helicopter -- 2.0.1 -- lib loader verification -- -- uses dcsCommon.isTroopCarrier(theUnit) -- 2.0.2 -- can now deploy from spawners with "requestable" attribute -- 2.1.0 -- supports config zones -- -- check spawner legality by types -- -- updated types to include 2.7.6 additions to infantry -- -- updated types to include stinger/manpads -- -- cfxHeloTroops -- a module to pick up and drop infantry. Can be used with any helo, -- might be used to configure to only certain -- currently only supports a single helicopter per group -- only helicopters that can transport troops will have this feature -- Copyright (c) 2021, 2022 by Christian Franz and cf/x AG -- cfxHeloTroops.requiredLibs = { "dcsCommon", -- common is of course needed for everything -- pretty stupid to check for this since we -- need common to invoke the check, but anyway "cfxZones", -- Zones, of course "cfxPlayer", -- player events "cfxCommander", -- to make troops do stuff "cfxGroundTroops", -- generic when dropping troops } cfxHeloTroops.unitConfigs = {} -- all configs are stored by unit's name cfxHeloTroops.myEvents = {3, 4, 5} -- 3- takeoff, 4 - land, 5 - crash cfxHeloTroops.legalTroops = {"Soldier AK", "Infantry AK", "Infantry AK ver2", "Infantry AK ver3", "Infantry AK Ins", "Soldier M249", "Soldier M4 GRG", "Soldier M4", "Soldier RPG", "Paratrooper AKS-74", "Paratrooper RPG-16", "Stinger comm dsr", "Stinger comm", "Soldier stinger", "SA-18 Igla-S comm", "SA-18 Igla-S manpad", "Igla manpad INS", "SA-18 Igla comm", "SA-18 Igla manpad",} cfxHeloTroops.troopWeight = 100 -- kg average weight per trooper function cfxHeloTroops.resetConfig(conf) conf.autoDrop = cfxHeloTroops.autoDrop --if true, will drop troops on-board upon touchdown conf.autoPickup = cfxHeloTroops.autoPickup -- if true will load nearest troops upon touchdown conf.pickupRange = cfxHeloTroops.pickupRange --meters, maybe make per helo? -- maybe set up max seats by type conf.currentState = -1 -- 0 = landed, 1 = airborne, -1 undetermined conf.troopsOnBoardNum = 0 -- if not 0, we have troops and can spawnm/drop conf.troopCapacity = 8 -- should be depending on airframe conf.troopsOnBoard = {} -- table with the following conf.troopsOnBoard.name = "***reset***" conf.dropFormation = "circle_out" -- may be chosen later? end function cfxHeloTroops.createDefaultConfig(theUnit) local conf = {} cfxHeloTroops.resetConfig(conf) conf.myMainMenu = nil -- this is where the main menu for group will be stored conf.myCommands = nil -- this is where we put all teh commands in return conf end function cfxHeloTroops.getUnitConfig(theUnit) -- will create new config if not existing if not theUnit then trigger.action.outText("+++WARNING: nil unit in get config!", 30) return nil end local c = cfxHeloTroops.unitConfigs[theUnit:getName()] if not c then c = cfxHeloTroops.createDefaultConfig(theUnit) cfxHeloTroops.unitConfigs[theUnit:getName()] = c end return c end function cfxHeloTroops.getConfigForUnitNamed(aName) return cfxHeloTroops.unitConfigs[aName] end function cfxHeloTroops.removeConfigForUnitNamed(aName) if cfxHeloTroops.unitConfigs[aName] then cfxHeloTroops.unitConfigs[aName] = nil end end function cfxHeloTroops.setState(theUnit, isLanded) -- called to set the current state of the helicopter (group) -- currently one helicopter per group max end -- -- E V E N T H A N D L I N G -- function cfxHeloTroops.isInteresting(eventID) -- return true if we are interested in this event, false else for key, evType in pairs(cfxHeloTroops.myEvents) do if evType == eventID then return true end end return false end function cfxHeloTroops.preProcessor(event) -- make sure it has an initiator if not event.initiator then return false end -- no initiator local theUnit = event.initiator if not cfxPlayer.isPlayerUnit(theUnit) then return false end -- not a player unit local cat = theUnit:getCategory() if cat ~= Group.Category.HELICOPTER then return false end return cfxHeloTroops.isInteresting(event.id) end function cfxHeloTroops.postProcessor(event) -- don't do anything end function cfxHeloTroops.somethingHappened(event) -- when this is invoked, the preprocessor guarantees that -- it's an interesting event -- unit is valid and player -- airframe category is helicopter local theUnit = event.initiator local ID = event.id local myType = theUnit:getTypeName() if ID == 4 then cfxHeloTroops.heloLanded(theUnit) end if ID == 3 then cfxHeloTroops.heloDeparted(theUnit) end if ID == 5 then cfxHeloTroops.heloCrashed(theUnit) end cfxHeloTroops.setCommsMenu(theUnit) end -- -- -- LANDED -- -- function cfxHeloTroops.loadClosestGroup(conf) local p = conf.unit:getPosition().p local cat = Group.Category.GROUND local unitsToLoad = dcsCommon.getLivingGroupsAndDistInRangeToPoint(p, conf.pickupRange, conf.unit:getCoalition(), cat) -- now, the groups may contain units that are not for transport. -- later we can filter this by weight, or other cool stuff -- for now we simply only troopy with legal type strings unitsToLoad = cfxHeloTroops.filterTroopsByType(unitsToLoad) -- now limit the options to the five closest legal groups local numUnits = #unitsToLoad if numUnits < 1 then return false end -- on false will drop through local aTeam = unitsToLoad[1] -- get first (closest) entry local dist = aTeam.dist local group = aTeam.group cfxHeloTroops.doLoadGroup({conf, group}) return true -- will have loaded and reset menu end function cfxHeloTroops.heloLanded(theUnit) -- when we have landed, if not dcsCommon.isTroopCarrier(theUnit) then return end local conf = cfxHeloTroops.getUnitConfig(theUnit) conf.unit = theUnit conf.currentState = 0 -- we look if we auto-unload if conf.autoDrop then if conf.troopsOnBoardNum > 0 then cfxHeloTroops.doDeployTroops({conf, "autodrop"}) -- already called set menu, can exit directly return end -- when we get here, we have no troops to drop on board -- so nothing to do really except look if we can pick up troops -- set menu will do that for us end if conf.autoPickup then if conf.troopsOnBoardNum < 1 then -- load the closest group if cfxHeloTroops.loadClosestGroup(conf) then return end end end -- when we get here, we simply set the newest menus and are done -- reset menu cfxHeloTroops.removeComms(conf.unit) cfxHeloTroops.setCommsMenu(conf.unit) end -- -- -- Helo took off -- -- function cfxHeloTroops.heloDeparted(theUnit) if not dcsCommon.isTroopCarrier(theUnit) then return end -- when we take off, all that needs to be done is to change the state -- to airborne, and then set the status flag local conf = cfxHeloTroops.getUnitConfig(theUnit) conf.currentState = 1 -- in the air cfxHeloTroops.removeComms(conf.unit) cfxHeloTroops.setCommsMenu(conf.unit) end -- -- -- Helo Crashed -- -- function cfxHeloTroops.heloCrashed(theUnit) if not dcsCommon.isTroopCarrier(theUnit) then return end -- clean up local conf = cfxHeloTroops.getUnitConfig(theUnit) conf.unit = theUnit conf.troopsOnBoardNum = 0 -- all dead conf.currentState = -1 -- (we don't know) -- conf.troopsOnBoardTypes = "" -- no troops, remember? conf.troopsOnBoard = {} cfxHeloTroops.removeComms(conf.unit) end -- -- -- M E N U H A N D L I N G & R E S P O N S E -- -- function cfxHeloTroops.clearCommsSubmenus(conf) if conf.myCommands then for i=1, #conf.myCommands do missionCommands.removeItemForGroup(conf.id, conf.myCommands[i]) end end conf.myCommands = {} end function cfxHeloTroops.removeCommsFromConfig(conf) cfxHeloTroops.clearCommsSubmenus(conf) if conf.myMainMenu then missionCommands.removeItemForGroup(conf.id, conf.myMainMenu) conf.myMainMenu = nil end end function cfxHeloTroops.removeComms(theUnit) if not theUnit then return end if not theUnit:isExist() then return end local group = theUnit:getGroup() local id = group:getID() local conf = cfxHeloTroops.getUnitConfig(theUnit) conf.id = id conf.unit = theUnit cfxHeloTroops.removeCommsFromConfig(conf) end function cfxHeloTroops.addConfigMenu(conf) -- we add the a menu showing current state -- and the option to change fro auto drop -- and auto pickup local onOff = "OFF" if conf.autoDrop then onOff = "ON" end local theCommand = missionCommands.addCommandForGroup( conf.id, 'Auto-Drop: ' .. onOff .. ' - Select to change', conf.myMainMenu, cfxHeloTroops.redirectToggleConfig, {conf, "drop"} ) table.insert(conf.myCommands, theCommand) onOff = "OFF" if conf.autoPickup then onOff = "ON" end theCommand = missionCommands.addCommandForGroup( conf.id, 'Auto-Pickup: ' .. onOff .. ' - Select to change', conf.myMainMenu, cfxHeloTroops.redirectToggleConfig, {conf, "pickup"} ) table.insert(conf.myCommands, theCommand) end function cfxHeloTroops.setCommsMenu(theUnit) -- depending on own load state, we set the command structure -- it begins at 10-other, and has 'Assault Troops' as main menu with submenus -- as required if not theUnit then return end if not theUnit:isExist() then return end -- we only add this menu to troop carriers if not dcsCommon.isTroopCarrier(theUnit) then return end local group = theUnit:getGroup() local id = group:getID() local conf = cfxHeloTroops.getUnitConfig(theUnit) --cfxHeloTroops.unitConfigs[theUnit:getName()] conf.id = id; -- we do this ALWAYS to it is current even after a crash conf.unit = theUnit -- link back --local conf = cfxHeloTroops.getUnitConfig(theUnit) -- ok, first, if we don't have an F-10 menu, create one if not (conf.myMainMenu) then conf.myMainMenu = missionCommands.addSubMenuForGroup(id, 'Airlift Troops') end -- clear out existing commands cfxHeloTroops.clearCommsSubmenus(conf) -- now we have a menu without submenus. -- add our own submenus cfxHeloTroops.addConfigMenu(conf) -- now see if we are on the ground or in the air -- or unknown if conf.currentState < 0 then conf.currentState = 0 -- landed if theUnit:inAir() then conf.currentState = 1 end end if conf.currentState == 0 then cfxHeloTroops.addGroundMenu(conf) else cfxHeloTroops.addAirborneMenu(conf) end end function cfxHeloTroops.addAirborneMenu(conf) -- while we are airborne, there isn't much to do except add a status menu that does nothing -- but we can add some instructions -- let's begin by assuming no troops aboard local commandTxt = "(To load troops, land in proximity to them)" if conf.troopsOnBoardNum > 0 then commandTxt = "(You are carrying " .. conf.troopsOnBoardNum .. " Assault Troops. Land to deploy them" end local theCommand = missionCommands.addCommandForGroup( conf.id, commandTxt, conf.myMainMenu, cfxHeloTroops.redirectNoAction, {conf, "none"} ) table.insert(conf.myCommands, theCommand) end function cfxHeloTroops.redirectNoAction(args) -- actually, we do not redirect since there is nothing to do end function cfxHeloTroops.addGroundMenu(conf) -- this is the most complex menu. Player can deploy troops when loaded -- and load troops when they are in proximity -- case 1: troops aboard if conf.troopsOnBoardNum > 0 then local theCommand = missionCommands.addCommandForGroup( conf.id, "Deploy Team <" .. conf.troopsOnBoard.name .. ">", conf.myMainMenu, cfxHeloTroops.redirectDeployTroops, {conf, "deploy"} ) table.insert(conf.myCommands, theCommand) return end -- case 2A: no troops aboard, and spawners in range -- that are requestable local p = conf.unit:getPosition().p local mySide = conf.unit:getCoalition() if cfxSpawnZones then -- only if SpawnZones is implemented local availableSpawnersRaw = cfxSpawnZones.getRequestableSpawnersInRange(p, 500, mySide) -- DONE: requestable spawners must check for troop compatibility local availableSpawners = {} for idx, aSpawner in pairs(availableSpawnersRaw) do -- filter all spawners that spawn "illegal" troops local theTypes = aSpawner.types local typeArray = dcsCommon.splitString(theTypes, ',') typeArray = dcsCommon.trimArray(typeArray) local allLegal = true for idy, aType in pairs(typeArray) do if not dcsCommon.arrayContainsString(cfxHeloTroops.legalTroops, aType) then allLegal = false end end if allLegal then table.insert(availableSpawners, aSpawner) end end local numSpawners = #availableSpawners if numSpawners > 5 then numSpawners = 5 end while numSpawners > 0 do -- for each spawner in range, create a -- spawn menu item local spawner = availableSpawners[numSpawners] local theName = spawner.baseName local comm = "Request <" .. theName .. "> troops for transport" -- .. math.floor(aTeam.dist) .. "m away" local theCommand = missionCommands.addCommandForGroup( conf.id, comm, conf.myMainMenu, cfxHeloTroops.redirectSpawnGroup, {conf, spawner} ) table.insert(conf.myCommands, theCommand) numSpawners = numSpawners - 1 end end -- case 2B: no troops aboard. see if there are troops around -- that we can load up local cat = Group.Category.GROUND local unitsToLoad = dcsCommon.getLivingGroupsAndDistInRangeToPoint(p, conf.pickupRange, conf.unit:getCoalition(), cat) -- now, the groups may contain units that are not for transport. -- later we can filter this by weight, or other cool stuff -- for now we simply only troopy with legal type strings -- TODO: add weight filtering unitsToLoad = cfxHeloTroops.filterTroopsByType(unitsToLoad) -- now limit the options to the five closest legal groups local numUnits = #unitsToLoad if numUnits > 5 then numUnits = 5 end if numUnits < 1 then local theCommand = missionCommands.addCommandForGroup( conf.id, "(No units in range)", conf.myMainMenu, cfxHeloTroops.redirectNoAction, {conf, "none"} ) table.insert(conf.myCommands, theCommand) return end -- add an entry for each group in units to load for i=1, numUnits do local aTeam = unitsToLoad[i] local dist = aTeam.dist local group = aTeam.group local tNum = group:getSize() local comm = "Load <" .. group:getName() .. "> " .. tNum .. " Members" -- .. math.floor(aTeam.dist) .. "m away" local theCommand = missionCommands.addCommandForGroup( conf.id, comm, conf.myMainMenu, cfxHeloTroops.redirectLoadGroup, {conf, group} ) table.insert(conf.myCommands, theCommand) end end function cfxHeloTroops.filterTroopsByType(unitsToLoad) local filteredGroups = {} for idx, aTeam in pairs(unitsToLoad) do local group = aTeam.group local theTypes = dcsCommon.getGroupTypeString(group) local aT = dcsCommon.splitString(theTypes, ",") local pass = true for iT, sT in pairs(aT) do -- check if this is a valid type if not dcsCommon.arrayContainsString(cfxHeloTroops.legalTroops, sT) then pass = false break end end if pass then table.insert(filteredGroups, aTeam) end end return filteredGroups end -- -- T O G G L E S -- function cfxHeloTroops.redirectToggleConfig(args) timer.scheduleFunction(cfxHeloTroops.doToggleConfig, args, timer.getTime() + 0.1) end function cfxHeloTroops.doToggleConfig(args) local conf = args[1] local what = args[2] if what == "drop" then conf.autoDrop = not conf.autoDrop if conf.autoDrop then trigger.action.outTextForGroup(conf.id, "Now deploying troops immediately after landing", 30) else trigger.action.outTextForGroup(conf.id, "Troops will now only deploy when told to", 30) end else conf.autoPickup = not conf.autoPickup if conf.autoPickup then trigger.action.outTextForGroup(conf.id, "Nearest troops will now automatically board after landing", 30) else trigger.action.outTextForGroup(conf.id, "Troops will now board only after being ordered to do so", 30) end end cfxHeloTroops.setCommsMenu(conf.unit) end -- -- Deploying Troops -- function cfxHeloTroops.redirectDeployTroops(args) timer.scheduleFunction(cfxHeloTroops.doDeployTroops, args, timer.getTime() + 0.1) end function cfxHeloTroops.doDeployTroops(args) local conf = args[1] local what = args[2] -- deploy the troops I have on board in formation cfxHeloTroops.deployTroopsFromHelicopter(conf) -- set own troops to 0 and erase type string conf.troopsOnBoardNum = 0 conf.troopsOnBoard = {} -- conf.troopsOnBoardTypes = "" conf.troopsOnBoard.name = "***wasdeployed***" -- reset menu cfxHeloTroops.removeComms(conf.unit) cfxHeloTroops.setCommsMenu(conf.unit) end function cfxHeloTroops.deployTroopsFromHelicopter(conf) -- we have troops, drop them now local unitTypes = {} -- build type names local theUnit = conf.unit local p = theUnit:getPoint() --for i=1, scenario.troopSize[theUnit:getName()] do -- table.insert(unitTypes, "Soldier M4") --end -- split the conf.troopsOnBoardTypes into an array of types unitTypes = dcsCommon.splitString(conf.troopsOnBoard.types, ",") if #unitTypes < 1 then table.insert(unitTypes, "Soldier M4") -- make it one m4 trooper as fallback end local range = conf.troopsOnBoard.range local orders = conf.troopsOnBoard.orders if not orders then orders = "guard" end -- order processing: if the orders were pre-pended with "wait-" -- we now remove that, so after dropping they do what their -- orders where AFTER being picked up if dcsCommon.stringStartsWith(orders, "wait-") then orders = dcsCommon.removePrefix(orders, "wait-") trigger.action.outTextForGroup(conf.id, "+++ <" .. conf.troopsOnBoard.name .. "> revoke 'wait' orders, proceed with <".. orders .. ">", 30) end local chopperZone = cfxZones.createSimpleZone("choppa", p, 12) -- 12 m ratius around choppa --local theCoalition = theUnit:getCountry() -- make it choppers country local theCoalition = theUnit:getGroup():getCoalition() -- make it choppers COALITION local theGroup = cfxZones.createGroundUnitsInZoneForCoalition ( theCoalition, conf.troopsOnBoard.name, -- dcsCommon.uuid("Assault"), -- maybe use config name as loaded from the group chopperZone, unitTypes, conf.dropFormation, 90) local troop = cfxGroundTroops.createGroundTroops(theGroup, range, orders) -- use default range and orders -- instead of scheduling tasking in one second, we add to -- ground troops pool, and the troop pool manager will assign some enemies cfxGroundTroops.addGroundTroopsToPool(troop) trigger.action.outTextForGroup(conf.id, "<" .. theGroup:getName() .. "> have deployed to the ground with orders " .. orders .. "!", 30) end -- -- Loading Troops -- function cfxHeloTroops.redirectLoadGroup(args) timer.scheduleFunction(cfxHeloTroops.doLoadGroup, args, timer.getTime() + 0.1) end function cfxHeloTroops.doLoadGroup(args) local conf = args[1] local group = args[2] conf.troopsOnBoard = {} -- all we need to do is disassemble the group into type conf.troopsOnBoard.types = dcsCommon.getGroupTypeString(group) -- get the size conf.troopsOnBoardNum = group:getSize() -- and name conf.troopsOnBoard.name = group:getName() -- and put it all into the helicopter config -- now we need to destroy the group. First, remove it from the pool local pooledGroup = cfxGroundTroops.getGroundTroopsForGroup(group) if pooledGroup then -- copy some important info from the troops -- if they are set conf.troopsOnBoard.orders = pooledGroup.orders conf.troopsOnBoard.range = pooledGroup.range cfxGroundTroops.removeTroopsFromPool(pooledGroup) trigger.action.outTextForGroup(conf.id, "Team '".. conf.troopsOnBoard.name .."' loaded and has orders <" .. conf.troopsOnBoard.orders .. ">", 30) else --trigger.action.outTextForGroup(conf.id, "Team '".. conf.troopsOnBoard.name .."' loaded!", 30) if cfxHeloTroops.verbose then trigger.action.outText("+++heloT: ".. conf.troopsOnBoard.name .." was not committed to ground troops", 30) end end -- now simply destroy the group -- we'll re-assemble it when we deploy it -- we currently can't change the weight of the helicopter -- TODO: add weight changing code -- TODO: ensure compatibility with CSAR module group:destroy() -- say so trigger.action.outTextForGroup(conf.id, "Team '".. conf.troopsOnBoard.name .."' aboard, ready to go!", 30) -- reset menu cfxHeloTroops.removeComms(conf.unit) cfxHeloTroops.setCommsMenu(conf.unit) end -- -- spawning troops -- function cfxHeloTroops.redirectSpawnGroup(args) timer.scheduleFunction(cfxHeloTroops.doSpawnGroup, args, timer.getTime() + 0.1) end function cfxHeloTroops.delayedCommsResetForUnit(args) local theUnit = args[1] cfxHeloTroops.removeComms(theUnit) cfxHeloTroops.setCommsMenu(theUnit) end function cfxHeloTroops.doSpawnGroup(args) local conf = args[1] local theSpawner = args[2] -- make sure cooldown on spawner has timed out, else -- notify that you have to wait local now = timer.getTime() if now < (theSpawner.lastSpawnTimeStamp + theSpawner.cooldown) then local delta = math.floor(theSpawner.lastSpawnTimeStamp + theSpawner.cooldown - now) trigger.action.outTextForGroup(conf.id, "Still redeploying (" .. delta .. " seconds left)", 30) return end cfxSpawnZones.spawnWithSpawner(theSpawner) trigger.action.outTextForGroup(conf.id, "Deploying <" .. theSpawner.baseName .. "> now...", 30) -- reset all comms so we can include new troops -- into load menu timer.scheduleFunction(cfxHeloTroops.delayedCommsResetForUnit, {conf.unit, "ignore"}, now + 1.0) end -- -- Player event callbacks -- function cfxHeloTroops.playerChangeEvent(evType, description, player, data) if evType == "newGroup" then theUnit = data.primeUnit cfxHeloTroops.setCommsMenu(theUnit) return end if evType == "removeGroup" then -- trigger.action.outText("+++Helo Troops: a group disappeared", 30) -- data.name contains the name of the group. nil the entry in config list, so all -- troops that group was carrying are gone -- we must remove the comms menu for this group else we try to add another one to this group later -- we assume a one-unit group structure, else the following may fail local conf = cfxHeloTroops.getConfigForUnitNamed(data.primeUnitName) if conf then cfxHeloTroops.removeCommsFromConfig(conf) end return end if evType == "leave" then local conf = cfxHeloTroops.getConfigForUnitNamed(player.unitName) if conf then cfxHeloTroops.resetConfig(conf) end end if evType == "unit" then -- player changed units. almost never in MP, but possible in solo -- we need to reset the conf so no troops are carried any longer local conf = cfxHeloTroops.getConfigForUnitNamed(data.oldUnitName) if conf then cfxHeloTroops.resetConfig(conf) end end end -- -- read config zone -- function cfxHeloTroops.readConfigZone() -- note: must match exactly!!!! local theZone = cfxZones.getZoneByName("heloTroopsConfig") if not theZone then trigger.action.outText("+++heloT: no config zone!", 30) return end cfxHeloTroops.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false) if cfxZones.hasProperty(theZone, "legalTroops") then local theTypesString = cfxZones.getStringFromZoneProperty(theZone, "legalTroops", "") local unitTypes = dcsCommon.splitString(aSpawner.types, ",") if #unitTypes < 1 then unitTypes = {"Soldier AK", "Infantry AK", "Infantry AK ver2", "Infantry AK ver3", "Infantry AK Ins", "Soldier M249", "Soldier M4 GRG", "Soldier M4", "Soldier RPG", "Paratrooper AKS-74", "Paratrooper RPG-16", "Stinger comm dsr", "Stinger comm", "Soldier stinger", "SA-18 Igla-S comm", "SA-18 Igla-S manpad", "Igla manpad INS", "SA-18 Igla comm", "SA-18 Igla manpad",} -- default else unitTypes = dcsCommon.trimArray(unitTypes) end cfxHeloTroops.legalTroops = unitTypes end cfxHeloTroops.troopWeight = cfxZones.getNumberFromZoneProperty(theZone, "troopWeight", 100) -- kg average weight per trooper cfxHeloTroops.autoDrop = cfxZones.getBoolFromZoneProperty(theZone, "autoDrop", false) cfxHeloTroops.autoPickup = cfxZones.getBoolFromZoneProperty(theZone, "autoPickup", false) cfxHeloTroops.pickupRange = cfxZones.getNumberFromZoneProperty(theZone, "pickupRange", 100) end -- -- Start -- function cfxHeloTroops.start() -- check libs if not dcsCommon.libCheck("cfx Helo Troops", cfxHeloTroops.requiredLibs) then return false end -- read config zone -- install callbacks for helo-relevant events dcsCommon.addEventHandler(cfxHeloTroops.somethingHappened, cfxHeloTroops.preProcessor, cfxHeloTroops.postProcessor) -- now iterate through all player groups and install the Assault Troop Menu allPlayerGroups = cfxPlayerGroups -- cfxPlayerGroups is a global, don't fuck with it! -- contains per group a player record, use prime unit to access player's unit for gname, pgroup in pairs(allPlayerGroups) do local aUnit = pgroup.primeUnit -- get any unit of that group cfxHeloTroops.setCommsMenu(aUnit) end -- now install the new group notifier to install Assault Troops menu cfxPlayer.addMonitor(cfxHeloTroops.playerChangeEvent) trigger.action.outText("cf/x Helo Troops v" .. cfxHeloTroops.version .. " started", 30) return true end -- let's get rolling if not cfxHeloTroops.start() then trigger.action.outText("cf/x Helo Troops aborted: missing libraries", 30) cfxHeloTroops = nil end --[[-- - interface with spawnable: request troops via comms menu if - spawnZones defined - spawners in range and - spawner auf 'paused' und 'requestable' --]]-- -- TODO: weight when loading troops