mirror of
https://github.com/weyne85/DML.git
synced 2025-10-29 16:57:49 +00:00
Version 2.2.4
Slotty and friends
This commit is contained in:
parent
07a32bd051
commit
8b4080c218
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
|||||||
FARPZones = {}
|
FARPZones = {}
|
||||||
FARPZones.version = "2.1.0"
|
FARPZones.version = "2.1.1"
|
||||||
FARPZones.verbose = false
|
FARPZones.verbose = false
|
||||||
--[[--
|
--[[--
|
||||||
Version History
|
Version History
|
||||||
@ -24,7 +24,7 @@ FARPZones.verbose = false
|
|||||||
2.0.2 - clean-up
|
2.0.2 - clean-up
|
||||||
verbosity enhancements
|
verbosity enhancements
|
||||||
2.1.0 - integration with camp: needs repairs, produceResourceVehicles()
|
2.1.0 - integration with camp: needs repairs, produceResourceVehicles()
|
||||||
|
2.1.1 - loading a farp from data respaws all defenders and resource vehicles
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
@ -547,6 +547,8 @@ function FARPZones.loadMission()
|
|||||||
local theAB = theFARP.mainFarp
|
local theAB = theFARP.mainFarp
|
||||||
theAB:setCoalition(theFARP.owner) -- FARP is in lockup.
|
theAB:setCoalition(theFARP.owner) -- FARP is in lockup.
|
||||||
theFARP.defenderData = dcsCommon.clone(fData.defenderData)
|
theFARP.defenderData = dcsCommon.clone(fData.defenderData)
|
||||||
|
|
||||||
|
--[[--
|
||||||
local groupData = fData.defenderData
|
local groupData = fData.defenderData
|
||||||
if groupData and #groupData.units > 0 then
|
if groupData and #groupData.units > 0 then
|
||||||
local cty = groupData.cty
|
local cty = groupData.cty
|
||||||
@ -560,11 +562,13 @@ function FARPZones.loadMission()
|
|||||||
local cat = groupData.cat
|
local cat = groupData.cat
|
||||||
theFARP.resources = coalition.addGroup(cty, cat, groupData)
|
theFARP.resources = coalition.addGroup(cty, cat, groupData)
|
||||||
end
|
end
|
||||||
|
--]]--
|
||||||
|
FARPZones.produceVehicles(theFARP) -- do full defender and resource cycle
|
||||||
FARPZones.drawFARPCircleInMap(theFARP) -- mark in map
|
FARPZones.drawFARPCircleInMap(theFARP) -- mark in map
|
||||||
if (not theFARP.defenders) and (not theFARP.resources) then
|
-- if (not theFARP.defenders) and (not theFARP.resources) then
|
||||||
-- we instigate a resource and defender drop
|
-- we instigate a resource and defender drop
|
||||||
FARPZones.produceVehicles(theFARP)
|
-- FARPZones.produceVehicles(theFARP)
|
||||||
end
|
-- end
|
||||||
else
|
else
|
||||||
trigger.action.outText("frpZ: persistence: FARP <" .. fName .. "> no longer exists in mission, skipping", 30)
|
trigger.action.outText("frpZ: persistence: FARP <" .. fName .. "> no longer exists in mission, skipping", 30)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cfxSSBClient = {}
|
cfxSSBClient = {}
|
||||||
cfxSSBClient.version = "4.0.0"
|
cfxSSBClient.version = "4.0.1"
|
||||||
cfxSSBClient.verbose = false
|
cfxSSBClient.verbose = false
|
||||||
cfxSSBClient.singleUse = false -- set to true to block crashed planes
|
cfxSSBClient.singleUse = false -- set to true to block crashed planes
|
||||||
-- NOTE: singleUse (true) requires SSB to disable immediate respawn after kick
|
-- NOTE: singleUse (true) requires SSB to disable immediate respawn after kick
|
||||||
@ -16,6 +16,8 @@ cfxSSBClient.requiredLibs = {
|
|||||||
Version History
|
Version History
|
||||||
4.0.0 - dmlZones
|
4.0.0 - dmlZones
|
||||||
- cfxMX instead of cfxGroups
|
- cfxMX instead of cfxGroups
|
||||||
|
4.0.1 - check slot availability immediately upon start
|
||||||
|
- ssb autoenable option
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
cfxSSBClient.enabledFlagValue = 0 -- DO NOT CHANGE, MUST MATCH SSB
|
cfxSSBClient.enabledFlagValue = 0 -- DO NOT CHANGE, MUST MATCH SSB
|
||||||
@ -490,33 +492,31 @@ function cfxSSBClient.readConfigZone()
|
|||||||
-- note: must match exactly!!!!
|
-- note: must match exactly!!!!
|
||||||
local theZone = cfxZones.getZoneByName("SSBClientConfig")
|
local theZone = cfxZones.getZoneByName("SSBClientConfig")
|
||||||
if not theZone then
|
if not theZone then
|
||||||
trigger.action.outText("+++SSBC: no config zone!", 30)
|
theZone = cfxZones.createSimpleZone("SSBClientConfig")
|
||||||
return
|
end
|
||||||
end
|
cfxSSBClient.verbose = theZone.verbose
|
||||||
|
|
||||||
trigger.action.outText("+++SSBC: found config zone!", 30)
|
|
||||||
|
|
||||||
cfxSSBClient.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
|
||||||
|
|
||||||
-- single-use
|
-- single-use
|
||||||
cfxSSBClient.singleUse = cfxZones.getBoolFromZoneProperty(theZone, "singleUse", false) -- use airframes only once? respawn after kick must be disabled in ssb
|
cfxSSBClient.singleUse = theZone:getBoolFromZoneProperty("singleUse", false) -- use airframes only once? respawn after kick must be disabled in ssb
|
||||||
cfxSSBClient.reUseAfter = cfxZones.getNumberFromZoneProperty(theZone, "reUseAfter", -1)
|
cfxSSBClient.reUseAfter = theZone:getNumberFromZoneProperty( "reUseAfter", -1)
|
||||||
|
|
||||||
-- airfield availability
|
-- airfield availability
|
||||||
cfxSSBClient.allowNeutralFields = cfxZones.getBoolFromZoneProperty(theZone, "allowNeutralFields", false)
|
cfxSSBClient.allowNeutralFields = theZone:getBoolFromZoneProperty( "allowNeutralFields", false)
|
||||||
|
|
||||||
cfxSSBClient.maxAirfieldRange = cfxZones.getNumberFromZoneProperty(theZone, "maxAirfieldRange", 3000) -- meters, to find attached airfield
|
cfxSSBClient.maxAirfieldRange = theZone:getNumberFromZoneProperty("maxAirfieldRange", 3000) -- meters, to find attached airfield
|
||||||
|
|
||||||
-- optimization
|
-- optimization
|
||||||
|
|
||||||
cfxSSBClient.keepInAirGroups = cfxZones.getBoolFromZoneProperty(theZone, "keepInAirGroups", false)
|
cfxSSBClient.keepInAirGroups = theZone:getBoolFromZoneProperty("keepInAirGroups", false)
|
||||||
|
|
||||||
-- SSB direct control.
|
-- SSB direct control.
|
||||||
-- USE ONLY WHEN YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
-- USE ONLY WHEN YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||||
|
|
||||||
cfxSSBClient.enabledFlagValue = cfxZones.getNumberFromZoneProperty(theZone, "enabledFlagValue", 0)
|
cfxSSBClient.enabledFlagValue = theZone:getNumberFromZoneProperty("enabledFlagValue", 0)
|
||||||
|
|
||||||
cfxSSBClient.disabledFlagValue = cfxZones.getNumberFromZoneProperty(theZone, "disabledFlagValue", cfxSSBClient.enabledFlagValue + 100)
|
cfxSSBClient.disabledFlagValue = theZone:getNumberFromZoneProperty("disabledFlagValue", cfxSSBClient.enabledFlagValue + 100)
|
||||||
|
|
||||||
|
cfxSSBClient.ssbAutoenable = theZone:getBoolFromZoneProperty("ssbAutoenable", true)
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -601,13 +601,18 @@ function cfxSSBClient.start()
|
|||||||
|
|
||||||
-- install a timed update just to make sure
|
-- install a timed update just to make sure
|
||||||
-- and start NOW
|
-- and start NOW
|
||||||
timer.scheduleFunction(cfxSSBClient.update, {}, timer.getTime() + 1)
|
-- timer.scheduleFunction(cfxSSBClient.update, {}, timer.getTime() + 1)
|
||||||
|
cfxSSBClient.update()
|
||||||
|
|
||||||
-- start dml update (on a different timer
|
-- start dml update (on a different timer
|
||||||
cfxSSBClient.dmlUpdate()
|
cfxSSBClient.dmlUpdate()
|
||||||
|
|
||||||
-- now turn on ssb
|
-- now turn on ssb
|
||||||
trigger.action.setUserFlag("SSB",100)
|
if cfxSSBClient.ssbAutoenable then
|
||||||
|
trigger.action.setUserFlag("SSB",100)
|
||||||
|
else
|
||||||
|
trigger.action.outText("WARNING: cfxSSBClient did !!NOT!! auto-enable SSB for mission.", 30)
|
||||||
|
end
|
||||||
|
|
||||||
-- persistence: load states
|
-- persistence: load states
|
||||||
if persistence then
|
if persistence then
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
bombRange = {}
|
bombRange = {}
|
||||||
bombRange.version = "1.1.2"
|
bombRange.version = "1.1.3"
|
||||||
bombRange.dh = 1 -- meters above ground level burst
|
bombRange.dh = 1 -- meters above ground level burst
|
||||||
|
|
||||||
bombRange.requiredLibs = {
|
bombRange.requiredLibs = {
|
||||||
@ -21,6 +21,7 @@ VERSION HISTORY
|
|||||||
1.1.1 - fixed reading smoke color for zone
|
1.1.1 - fixed reading smoke color for zone
|
||||||
minor clean-up
|
minor clean-up
|
||||||
1.1.2 - corrected bug when no bomb range is detected
|
1.1.2 - corrected bug when no bomb range is detected
|
||||||
|
1.1.3 - added meters/feet distance when reporting impact
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
bombRange.bombs = {} -- live tracking
|
bombRange.bombs = {} -- live tracking
|
||||||
@ -543,7 +544,8 @@ function bombRange.impacted(weapon, target, finalPass)
|
|||||||
tDist = math.floor(tDist*100) /100
|
tDist = math.floor(tDist*100) /100
|
||||||
trigger.action.outTextForGroup(weapon.gID, "impact of " .. weapon.type .. " released by " .. weapon.pName .. " from " .. weapon.uType .. " after traveling " .. tDist .. " km in " .. t .. " sec, impact velocity at impact is " .. v .. " m/s!", 30)
|
trigger.action.outTextForGroup(weapon.gID, "impact of " .. weapon.type .. " released by " .. weapon.pName .. " from " .. weapon.uType .. " after traveling " .. tDist .. " km in " .. t .. " sec, impact velocity at impact is " .. v .. " m/s!", 30)
|
||||||
end
|
end
|
||||||
|
local meters = math.floor(minDist * 10) / 10
|
||||||
|
local feet = math.floor(minDist * 3.28084 * 10) / 10
|
||||||
local msg = ""
|
local msg = ""
|
||||||
if impactInside then
|
if impactInside then
|
||||||
local percentage = 0
|
local percentage = 0
|
||||||
@ -553,15 +555,17 @@ function bombRange.impacted(weapon, target, finalPass)
|
|||||||
percentage = 1 - (minDist / theRange.radius)
|
percentage = 1 - (minDist / theRange.radius)
|
||||||
percentage = math.floor(percentage * 100)
|
percentage = math.floor(percentage * 100)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
msg = "INSIDE target area"
|
msg = "INSIDE target area"
|
||||||
if theRange.reportName then msg = msg .. " " .. theRange.name end
|
if theRange.reportName then msg = msg .. " " .. theRange.name end
|
||||||
if (not targetName) and theRange.details then msg = msg .. ", off-center by " .. math.floor(minDist *10)/10 .. " m" end
|
if (not targetName) and theRange.details then msg = msg .. ", off-center by " .. meters .. "m/" .. feet .. "ft" end--math.floor(minDist *10)/10 .. " m" end
|
||||||
if targetName then msg = msg .. ", hit on " .. targetName end
|
if targetName then msg = msg .. ", hit on " .. targetName end
|
||||||
|
|
||||||
if not theRange.usePercentage then
|
if not theRange.usePercentage then
|
||||||
percentage = 100
|
percentage = 100
|
||||||
else
|
else
|
||||||
msg = msg .. " (Quality " .. percentage .."%)"
|
msg = msg .. " (Quality " .. percentage .."%)" --, off-center by " .. meters .. "m/" .. feet .. "ft)"
|
||||||
end
|
end
|
||||||
|
|
||||||
if theRange.hitOut then
|
if theRange.hitOut then
|
||||||
@ -572,7 +576,7 @@ function bombRange.impacted(weapon, target, finalPass)
|
|||||||
else
|
else
|
||||||
msg = "Outside target area"
|
msg = "Outside target area"
|
||||||
if theRange.reportName then msg = msg .. " " .. theRange.name end
|
if theRange.reportName then msg = msg .. " " .. theRange.name end
|
||||||
if theRange.details then msg = msg .. " (off-center by " .. math.floor(minDist *10)/10 .. " m)" end
|
if theRange.details then msg = msg .. " (off-center by " .. meters .. "m/" .. feet .. "ft)" end --math.floor(minDist *10)/10 .. " m)" end
|
||||||
msg = msg .. ", no hit."
|
msg = msg .. ", no hit."
|
||||||
bombRange.addImpactForWeapon(weapon, false, 0)
|
bombRange.addImpactForWeapon(weapon, false, 0)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
-- *** EXTENDS ZONES: 'pathing' attribute
|
-- *** EXTENDS ZONES: 'pathing' attribute
|
||||||
--
|
--
|
||||||
cfxCommander = {}
|
cfxCommander = {}
|
||||||
cfxCommander.version = "1.1.4"
|
cfxCommander.version = "2.0.0"
|
||||||
--[[-- VERSION HISTORY
|
--[[-- VERSION HISTORY
|
||||||
- 1.0.5 - createWPListForGroupToPointViaRoads: detect no road found
|
- 1.0.5 - createWPListForGroupToPointViaRoads: detect no road found
|
||||||
- 1.0.6 - build in more group checks in assign wp list
|
- 1.0.6 - build in more group checks in assign wp list
|
||||||
@ -30,7 +30,11 @@ cfxCommander.version = "1.1.4"
|
|||||||
- 1.1.3 - isExist() guard improvements for multiple methods
|
- 1.1.3 - isExist() guard improvements for multiple methods
|
||||||
- cleaned up comments
|
- cleaned up comments
|
||||||
- 1.1.4 - hardened makeGroupGoThere()
|
- 1.1.4 - hardened makeGroupGoThere()
|
||||||
|
- 2.0.0 - dml zones
|
||||||
|
- units now can move with moveFormation
|
||||||
|
- hardened performCommands()
|
||||||
|
- createWPListForGroupToPoint() supports moveFormation
|
||||||
|
- makeGroupGoTherePreferringRoads() supports moveFormation
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
cfxCommander.requiredLibs = {
|
cfxCommander.requiredLibs = {
|
||||||
@ -72,16 +76,11 @@ function cfxCommander.readConfigZone()
|
|||||||
-- note: must match exactly!!!!
|
-- note: must match exactly!!!!
|
||||||
local theZone = cfxZones.getZoneByName("CommanderConfig")
|
local theZone = cfxZones.getZoneByName("CommanderConfig")
|
||||||
if not theZone then
|
if not theZone then
|
||||||
trigger.action.outText("+++cmdr: no config zone!", 30)
|
theZone = cfxZones.createSimpleZone("CommanderConfig")
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
cfxCommander.verbose = theZone.verbose
|
||||||
trigger.action.outText("+++cmdr: found config zone!", 30)
|
cfxCommander.forceOffRoad = theZone:getBoolFromZoneProperty("forceOffRoad", false) -- if true, vehicles path follow roads, but may drive offroad
|
||||||
|
cfxCommander.noRoadsAtAll = theZone:getBoolFromZoneProperty("noRoadsAtAll", false)
|
||||||
cfxCommander.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
|
||||||
cfxCommander.forceOffRoad = cfxZones.getBoolFromZoneProperty(theZone, "forceOffRoad", false) -- if true, vehicles path follow roads, but may drive offroad
|
|
||||||
cfxCommander.noRoadsAtAll = cfxZones.getBoolFromZoneProperty(theZone, "noRoadsAtAll", false)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -118,8 +117,14 @@ function cfxCommander.performCommands(commandData)
|
|||||||
if not commandData.group then
|
if not commandData.group then
|
||||||
commandData.group = Group.getByName(commandData.name) -- better be inited!
|
commandData.group = Group.getByName(commandData.name) -- better be inited!
|
||||||
end
|
end
|
||||||
|
if not Group.isExist(commandData.group) then
|
||||||
|
-- something bad is happening
|
||||||
|
return nil
|
||||||
|
end
|
||||||
-- get the AI
|
-- get the AI
|
||||||
local theController = commandData.group:getController()
|
local theController = commandData.group:getController()
|
||||||
|
if not theController then return nil end
|
||||||
|
|
||||||
for i=1, #commandData.commands do
|
for i=1, #commandData.commands do
|
||||||
if cfxCommander.verbose then
|
if cfxCommander.verbose then
|
||||||
trigger.action.outText("Commander: performing " .. commandData.commands[i].id, 30)
|
trigger.action.outText("Commander: performing " .. commandData.commands[i].id, 30)
|
||||||
@ -204,7 +209,6 @@ function cfxCommander.doScheduledTask(data)
|
|||||||
local theGroup = data.group
|
local theGroup = data.group
|
||||||
if not theGroup then return end
|
if not theGroup then return end
|
||||||
if not Group.isExist(theGroup) then return end
|
if not Group.isExist(theGroup) then return end
|
||||||
-- if not theGroup.isExist then return end
|
|
||||||
|
|
||||||
local theController = theGroup:getController()
|
local theController = theGroup:getController()
|
||||||
theController:pushTask(data.task)
|
theController:pushTask(data.task)
|
||||||
@ -262,7 +266,7 @@ function cfxCommander.createBasicWaypoint(point, speed, formation)
|
|||||||
|
|
||||||
if not formation then formation = "Off Road" end
|
if not formation then formation = "Off Road" end
|
||||||
-- legal formations:
|
-- legal formations:
|
||||||
-- Off road
|
-- Off Road
|
||||||
-- On Road -- second letter upper case?
|
-- On Road -- second letter upper case?
|
||||||
-- Cone
|
-- Cone
|
||||||
-- Rank
|
-- Rank
|
||||||
@ -300,21 +304,22 @@ function cfxCommander.assignWPListToGroup(group, wpList, delay)
|
|||||||
local theTask = cfxCommander.buildTaskFromWPList(wpList)
|
local theTask = cfxCommander.buildTaskFromWPList(wpList)
|
||||||
local ctrl = group:getController()
|
local ctrl = group:getController()
|
||||||
|
|
||||||
--[[--
|
|
||||||
if delay < 0.001 then -- immediate action
|
|
||||||
if ctrl then
|
|
||||||
ctrl:setTask(theTask)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- delay execution of this command by the specified amount
|
|
||||||
-- of seconds
|
|
||||||
cfxCommander.scheduleTaskForGroup(group, theTask, delay)
|
|
||||||
end
|
|
||||||
--]]--
|
|
||||||
cfxCommander.scheduleTaskForGroup(group, theTask, delay)
|
cfxCommander.scheduleTaskForGroup(group, theTask, delay)
|
||||||
end
|
end
|
||||||
|
|
||||||
function cfxCommander.createWPListForGroupToPoint(group, point, speed, formation)
|
--[[--
|
||||||
|
Formations and their "action" keywords
|
||||||
|
Line Abreast = "Rank"
|
||||||
|
Cone = "Cone"
|
||||||
|
Vee = "Vee"
|
||||||
|
Diamond = "Diamond"
|
||||||
|
Echelon Left = "EchelonL"
|
||||||
|
Echelon Right = "EchelonR"
|
||||||
|
Custom = "Custom"
|
||||||
|
|
||||||
|
--]]--
|
||||||
|
|
||||||
|
function cfxCommander.createWPListForGroupToPoint(group, point, speed, moveFormation)
|
||||||
if type(group) == 'string' then -- group name
|
if type(group) == 'string' then -- group name
|
||||||
group = Group.getByName(group)
|
group = Group.getByName(group)
|
||||||
end
|
end
|
||||||
@ -323,8 +328,8 @@ function cfxCommander.createWPListForGroupToPoint(group, point, speed, formation
|
|||||||
-- here we are, and we want to go there. In DCS, this means that
|
-- here we are, and we want to go there. In DCS, this means that
|
||||||
-- we need to create a wp list consisting of here and there
|
-- we need to create a wp list consisting of here and there
|
||||||
local here = dcsCommon.getGroupLocation(group)
|
local here = dcsCommon.getGroupLocation(group)
|
||||||
local wpHere = cfxCommander.createBasicWaypoint(here, speed, formation)
|
local wpHere = cfxCommander.createBasicWaypoint(here, speed, moveFormation)
|
||||||
local wpThere = cfxCommander.createBasicWaypoint(point, speed, formation)
|
local wpThere = cfxCommander.createBasicWaypoint(point, speed, moveFormation)
|
||||||
wpList[1] = wpHere
|
wpList[1] = wpHere
|
||||||
wpList[2] = wpThere
|
wpList[2] = wpThere
|
||||||
return wpList
|
return wpList
|
||||||
@ -398,12 +403,9 @@ function cfxCommander.createWPListForGroupToPointViaRoads(group, point, speed)
|
|||||||
|
|
||||||
if pathLength > (2 * direct) then
|
if pathLength > (2 * direct) then
|
||||||
-- road takes too long, take direct approach
|
-- road takes too long, take direct approach
|
||||||
--trigger.action.outText("+++ road path (" .. pathLength .. ") > twice direct route(" .. direct .. "), commencing direct off-road", 30)
|
|
||||||
return cfxCommander.createWPListForGroupToPoint(group, point, speed)
|
return cfxCommander.createWPListForGroupToPoint(group, point, speed)
|
||||||
end
|
end
|
||||||
|
|
||||||
--trigger.action.outText("+++ ".. group:getName() .. ": choosing road path l=" .. pathLength .. " over direct route d=" .. direct, 30)
|
|
||||||
|
|
||||||
-- if we are here, the road trip is valid
|
-- if we are here, the road trip is valid
|
||||||
for idx, wp in pairs(rawRoadPoints) do
|
for idx, wp in pairs(rawRoadPoints) do
|
||||||
-- createBasic... supports w.xy format
|
-- createBasic... supports w.xy format
|
||||||
@ -422,16 +424,17 @@ function cfxCommander.createWPListForGroupToPointViaRoads(group, point, speed)
|
|||||||
return wpList
|
return wpList
|
||||||
end
|
end
|
||||||
|
|
||||||
function cfxCommander.makeGroupGoTherePreferringRoads(group, there, speed, delay)
|
function cfxCommander.makeGroupGoTherePreferringRoads(group, there, speed, delay, moveFormation)
|
||||||
if type(group) == 'string' then -- group name
|
if type(group) == 'string' then -- group name
|
||||||
group = Group.getByName(group)
|
group = Group.getByName(group)
|
||||||
end
|
end
|
||||||
if not delay then delay = 0 end
|
if not delay then delay = 0 end
|
||||||
|
|
||||||
|
if not moveFormation then moveFormation = "Off Road" end
|
||||||
|
|
||||||
if cfxCommander.noRoadsAtAll then
|
if cfxCommander.noRoadsAtAll then
|
||||||
-- we don't even follow roads, completely forced off
|
-- we don't even follow roads, completely forced off
|
||||||
cfxCommander.makeGroupGoThere(group, there, speed, "Off Road", delay)
|
cfxCommander.makeGroupGoThere(group, there, speed, moveFormation, delay)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -443,7 +446,7 @@ function cfxCommander.makeGroupGoTherePreferringRoads(group, there, speed, delay
|
|||||||
local oRide = cfxCommander.hasPathZoneFor(here, there)
|
local oRide = cfxCommander.hasPathZoneFor(here, there)
|
||||||
if oRide and oRide.pathing == "offroad" then
|
if oRide and oRide.pathing == "offroad" then
|
||||||
-- yup, override road preference
|
-- yup, override road preference
|
||||||
cfxCommander.makeGroupGoThere(group, there, speed, "Off Road", delay)
|
cfxCommander.makeGroupGoThere(group, there, speed, moveFormation, delay)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -498,9 +501,6 @@ function cfxCommander.start()
|
|||||||
|
|
||||||
-- identify and process all 'pathing' zones
|
-- identify and process all 'pathing' zones
|
||||||
local pathZones = cfxZones.getZonesWithAttributeNamed("pathing")
|
local pathZones = cfxZones.getZonesWithAttributeNamed("pathing")
|
||||||
|
|
||||||
-- now create a spawner for all, add them to the spawner updater, and spawn for all zones that are not
|
|
||||||
-- paused
|
|
||||||
for k, aZone in pairs(pathZones) do
|
for k, aZone in pairs(pathZones) do
|
||||||
cfxCommander.processPathingZone(aZone) -- process attribute and add to zone
|
cfxCommander.processPathingZone(aZone) -- process attribute and add to zone
|
||||||
cfxCommander.addPathingZone(aZone) -- remember it so we can smoke it
|
cfxCommander.addPathingZone(aZone) -- remember it so we can smoke it
|
||||||
|
|||||||
@ -1075,7 +1075,7 @@ function csarManager.updateCSARMissions()
|
|||||||
else
|
else
|
||||||
local msg = aMission.name .. " confirmed KIA, repeat KIA. Abort CSAR."
|
local msg = aMission.name .. " confirmed KIA, repeat KIA. Abort CSAR."
|
||||||
trigger.action.outTextForCoalition(aMission.side, msg, 30)
|
trigger.action.outTextForCoalition(aMission.side, msg, 30)
|
||||||
trigger.action.outSoundForCoalition(aMission.side, csarManager.actionSound)
|
trigger.action.outSoundForCoalition(aMission.side, csarManager.lostSound)
|
||||||
csarManager.invokeCallbacks(aMission.side, false, 1, "KIA", aMission)
|
csarManager.invokeCallbacks(aMission.side, false, 1, "KIA", aMission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1765,4 +1765,6 @@ end
|
|||||||
|
|
||||||
-- may want to change if time limit was exceeded on return to tell
|
-- may want to change if time limit was exceeded on return to tell
|
||||||
player that they did not survive the transport
|
player that they did not survive the transport
|
||||||
|
|
||||||
|
- randomize smoke color if smoke color has more than one entries
|
||||||
--]]--
|
--]]--
|
||||||
@ -1,5 +1,5 @@
|
|||||||
dcsCommon = {}
|
dcsCommon = {}
|
||||||
dcsCommon.version = "3.0.6"
|
dcsCommon.version = "3.0.7"
|
||||||
--[[-- VERSION HISTORY
|
--[[-- VERSION HISTORY
|
||||||
3.0.0 - removed bad bug in stringStartsWith, only relevant if caseSensitive is false
|
3.0.0 - removed bad bug in stringStartsWith, only relevant if caseSensitive is false
|
||||||
- point2text new intsOnly option
|
- point2text new intsOnly option
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
cfxGroundTroops = {}
|
cfxGroundTroops = {}
|
||||||
cfxGroundTroops.version = "2.0.1"
|
cfxGroundTroops.version = "2.2.0"
|
||||||
cfxGroundTroops.ups = 1
|
cfxGroundTroops.ups = 0.25 -- every 4 seconds
|
||||||
cfxGroundTroops.verbose = false
|
cfxGroundTroops.verbose = false
|
||||||
cfxGroundTroops.requiredLibs = {
|
cfxGroundTroops.requiredLibs = {
|
||||||
"dcsCommon", -- common is of course needed for everything
|
"dcsCommon", -- common is of course needed for everything
|
||||||
@ -29,10 +29,11 @@ cfxGroundTroops.jtacCB = {} -- jtac callbacks, to be implemented
|
|||||||
|
|
||||||
2.0.0 - dmlZones
|
2.0.0 - dmlZones
|
||||||
- jtacSound
|
- jtacSound
|
||||||
- clanup
|
- cleanup
|
||||||
- jtacVerbose
|
- jtacVerbose
|
||||||
2.0.1 - small fiex ti checkPileUp()
|
2.0.1 - small fiex ti checkPileUp()
|
||||||
|
2.1.0 - captureandhold - oneshot attackowned
|
||||||
|
2.2.0 - moveFormation support
|
||||||
|
|
||||||
an entry into the deployed troop table has the following attributes
|
an entry into the deployed troop table has the following attributes
|
||||||
- group - the group
|
- group - the group
|
||||||
@ -41,6 +42,8 @@ cfxGroundTroops.jtacCB = {} -- jtac callbacks, to be implemented
|
|||||||
"laze" - will stay in place and try to laze visible vehicles in range
|
"laze" - will stay in place and try to laze visible vehicles in range
|
||||||
"attackOwnedZone" - interface to cfxOwnedZones module, seeks out
|
"attackOwnedZone" - interface to cfxOwnedZones module, seeks out
|
||||||
enemy zones to attack and capture them
|
enemy zones to attack and capture them
|
||||||
|
"captureandhold" - interface to ownedZones, seeks out nearest enemy
|
||||||
|
or neutral owned zone. once captured, it stays there
|
||||||
"wait-<some other orders>" do nothing. the "wait" prefix will be removed some time and <some other order> then revealed. Used at least by heloTroops
|
"wait-<some other orders>" do nothing. the "wait" prefix will be removed some time and <some other order> then revealed. Used at least by heloTroops
|
||||||
"train" - target dummies. ROE=HOLD, no ground loop
|
"train" - target dummies. ROE=HOLD, no ground loop
|
||||||
"attack" - transition to destination, once there, stop and
|
"attack" - transition to destination, once there, stop and
|
||||||
@ -53,6 +56,7 @@ cfxGroundTroops.jtacCB = {} -- jtac callbacks, to be implemented
|
|||||||
- lazeTarget - target currently lazing
|
- lazeTarget - target currently lazing
|
||||||
- lazeCode - laser code. default is 1688
|
- lazeCode - laser code. default is 1688
|
||||||
- moving - has been given orders to move somewhere already. used for first movement order with attack orders
|
- moving - has been given orders to move somewhere already. used for first movement order with attack orders
|
||||||
|
-- reduced ups to 0.24, updating troops every 4 seconds is fast enough
|
||||||
|
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
@ -169,9 +173,9 @@ function cfxGroundTroops.makeTroopsEngageEnemies(troop)
|
|||||||
|
|
||||||
-- we lerp to 2/3 of enemy location
|
-- we lerp to 2/3 of enemy location
|
||||||
there = dcsCommon.vLerp(from, there, 0.66)
|
there = dcsCommon.vLerp(from, there, 0.66)
|
||||||
|
local moveFormation = troop.moveFormation
|
||||||
local speed = 10 -- m/s = 10 km/h -- wait. 10 m/s is 36 km/h
|
local speed = 10 -- m/s = 10 km/h -- wait. 10 m/s is 36 km/h
|
||||||
cfxCommander.makeGroupGoThere(group, there, speed)
|
cfxCommander.makeGroupGoThere(group, there, speed, moveFormation)
|
||||||
local attask = cfxCommander.createAttackGroupCommand(enemies)
|
local attask = cfxCommander.createAttackGroupCommand(enemies)
|
||||||
cfxCommander.scheduleTaskForGroup(group, attask, 0.5)
|
cfxCommander.scheduleTaskForGroup(group, attask, 0.5)
|
||||||
troop.moving = true
|
troop.moving = true
|
||||||
@ -189,15 +193,20 @@ function cfxGroundTroops.makeTroopsEngageZone(troop)
|
|||||||
local enemyZone = troop.destination -- must be cfxZone
|
local enemyZone = troop.destination -- must be cfxZone
|
||||||
local from = dcsCommon.getGroupLocation(group)
|
local from = dcsCommon.getGroupLocation(group)
|
||||||
if not from then return end -- the group died
|
if not from then return end -- the group died
|
||||||
local there = enemyZone.point -- access zone position
|
local there = enemyZone:getPoint() -- access zone position
|
||||||
if not there then return end
|
if not there then return end
|
||||||
|
|
||||||
local speed = 14 -- m/s; 10 m/s = 36 km/h
|
local speed = 14 -- m/s; 10 m/s = 36 km/h
|
||||||
|
|
||||||
-- make troops stop in 1 second, then start in 5 seconds to give AI respite
|
-- make troops stop in 1 second, then start in 5 seconds to give AI respite
|
||||||
cfxCommander.makeGroupHalt(group, 1) -- 1 second delay
|
cfxCommander.makeGroupHalt(group, 1) -- 1 second delay
|
||||||
cfxCommander.makeGroupGoTherePreferringRoads(group, there, speed, 5)
|
if troop.orders == "captureandhold" then
|
||||||
|
-- direct capture never uses roads
|
||||||
|
cfxCommander.makeGroupGoThere(group, there, speed, troop.moveFormation, 5)
|
||||||
|
else
|
||||||
|
-- when we attack any owned zone, we prefer roads
|
||||||
|
cfxCommander.makeGroupGoTherePreferringRoads(group, there, speed, 5, troop.moveFormation)
|
||||||
|
end
|
||||||
-- remember that we have issued a move order
|
-- remember that we have issued a move order
|
||||||
troop.moving = true
|
troop.moving = true
|
||||||
end
|
end
|
||||||
@ -236,6 +245,10 @@ end
|
|||||||
-- are heading for is already owned by their side, then look for
|
-- are heading for is already owned by their side, then look for
|
||||||
-- the closest enemy zone, and cut attack orders to move there
|
-- the closest enemy zone, and cut attack orders to move there
|
||||||
function cfxGroundTroops.getClosestEnemyZone(troop)
|
function cfxGroundTroops.getClosestEnemyZone(troop)
|
||||||
|
if not cfxOwnedZones then
|
||||||
|
trigger.action.outText("+++groundT: WARNING! ownedZones is not loaded, which is required.", 30)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
local p = dcsCommon.getGroupLocation(troop.group)
|
local p = dcsCommon.getGroupLocation(troop.group)
|
||||||
local tempZone = cfxZones.createSimpleZone("tz", p, 100)
|
local tempZone = cfxZones.createSimpleZone("tz", p, 100)
|
||||||
tempZone.owner = troop.side
|
tempZone.owner = troop.side
|
||||||
@ -250,6 +263,17 @@ function cfxGroundTroops.updateZoneAttackers(troop)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
troop.insideDestination = false -- mark as not inside
|
troop.insideDestination = false -- mark as not inside
|
||||||
|
|
||||||
|
-- we *have* a destination, but not yet isued move orders,
|
||||||
|
-- meaning that we just spawned, probably from helo.
|
||||||
|
-- do not look for new location, issue move orders instead
|
||||||
|
if not troop.hasMovedOrders and troop.destination then
|
||||||
|
troop.hasMovedOrders = true
|
||||||
|
cfxGroundTroops.makeTroopsEngageZone(troop)
|
||||||
|
troop.lastOrderDate = timer.getTime()
|
||||||
|
troop.speedWarning = 0
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local newTargetZone = cfxGroundTroops.getClosestEnemyZone(troop)
|
local newTargetZone = cfxGroundTroops.getClosestEnemyZone(troop)
|
||||||
if not newTargetZone then
|
if not newTargetZone then
|
||||||
@ -259,6 +283,12 @@ function cfxGroundTroops.updateZoneAttackers(troop)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if newTargetZone ~= troop.destination then
|
if newTargetZone ~= troop.destination then
|
||||||
|
if troop.destination and troop.orders == "captureandhold" then
|
||||||
|
troop.lastOrderDate = timer.getTime() -- we may even dismiss them
|
||||||
|
-- from troop array. But orders should remain when picked up by helo
|
||||||
|
-- we never change target. Stay.
|
||||||
|
return
|
||||||
|
end
|
||||||
troop.destination = newTargetZone
|
troop.destination = newTargetZone
|
||||||
cfxGroundTroops.makeTroopsEngageZone(troop)
|
cfxGroundTroops.makeTroopsEngageZone(troop)
|
||||||
troop.lastOrderDate = timer.getTime()
|
troop.lastOrderDate = timer.getTime()
|
||||||
@ -532,6 +562,10 @@ function cfxGroundTroops.updateWait(troop)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function cfxGroundTroops.updateTroops(troop)
|
function cfxGroundTroops.updateTroops(troop)
|
||||||
|
if cfxGroundTroops.verbose then
|
||||||
|
trigger.action.outText("+++GTroop: enter updateTroopps for <" .. troop.name .. ">", 30)
|
||||||
|
end
|
||||||
|
|
||||||
-- if orders start with "wait-" then the troops
|
-- if orders start with "wait-" then the troops
|
||||||
-- simply do nothing
|
-- simply do nothing
|
||||||
if dcsCommon.stringStartsWith(troop.orders, "wait-") then
|
if dcsCommon.stringStartsWith(troop.orders, "wait-") then
|
||||||
@ -547,6 +581,9 @@ function cfxGroundTroops.updateTroops(troop)
|
|||||||
elseif troop.orders == "attackownedzone" then
|
elseif troop.orders == "attackownedzone" then
|
||||||
cfxGroundTroops.updateZoneAttackers(troop)
|
cfxGroundTroops.updateZoneAttackers(troop)
|
||||||
|
|
||||||
|
elseif troop.orders == "captureandhold" then
|
||||||
|
cfxGroundTroops.updateZoneAttackers(troop)
|
||||||
|
|
||||||
elseif troop.orders == "laze" then
|
elseif troop.orders == "laze" then
|
||||||
cfxGroundTroops.updateLaze(troop)
|
cfxGroundTroops.updateLaze(troop)
|
||||||
|
|
||||||
@ -880,14 +917,16 @@ end
|
|||||||
-- createGroundTroop
|
-- createGroundTroop
|
||||||
-- use this to create a cfxGroundTroops from a dcs group
|
-- use this to create a cfxGroundTroops from a dcs group
|
||||||
--
|
--
|
||||||
function cfxGroundTroops.createGroundTroops(inGroup, range, orders)
|
function cfxGroundTroops.createGroundTroops(inGroup, range, orders, moveFormation)
|
||||||
local newTroops = {}
|
local newTroops = {}
|
||||||
if not orders then
|
if not orders then
|
||||||
orders = "guard"
|
orders = "guard"
|
||||||
end
|
end
|
||||||
|
if not moveFormation then moveFormation = "Custom" end
|
||||||
if orders:lower() == "lase" then
|
if orders:lower() == "lase" then
|
||||||
orders = "laze" -- we use WRONG spelling here, cause we're cool. yeah, right.
|
orders = "laze" -- we use WRONG spelling here, cause we're cool. yeah, right.
|
||||||
end
|
end
|
||||||
|
trigger.action.outText("Enter createGT group <" .. inGroup:getName() .. "> with o=<" .. orders .. ">, mf=<" .. moveFormation .. ">", 30)
|
||||||
newTroops.insideDestination = false
|
newTroops.insideDestination = false
|
||||||
newTroops.unscheduleCount = 0 -- will count up as we aren't scheduled
|
newTroops.unscheduleCount = 0 -- will count up as we aren't scheduled
|
||||||
newTroops.speedWarning = 0
|
newTroops.speedWarning = 0
|
||||||
@ -897,6 +936,7 @@ function cfxGroundTroops.createGroundTroops(inGroup, range, orders)
|
|||||||
newTroops.coalition = inGroup:getCoalition()
|
newTroops.coalition = inGroup:getCoalition()
|
||||||
newTroops.side = newTroops.coalition -- because we'e been using both.
|
newTroops.side = newTroops.coalition -- because we'e been using both.
|
||||||
newTroops.name = inGroup:getName()
|
newTroops.name = inGroup:getName()
|
||||||
|
newTroops.moveFormation = moveFormation
|
||||||
newTroops.moving = false -- set to not have received move orders yet
|
newTroops.moving = false -- set to not have received move orders yet
|
||||||
newTroops.signature = "cfx" -- to verify this is groundTroop group, not dcs groups
|
newTroops.signature = "cfx" -- to verify this is groundTroop group, not dcs groups
|
||||||
if not range then range = 300 end
|
if not range then range = 300 end
|
||||||
@ -912,6 +952,7 @@ function cfxGroundTroops.addGroundTroopsToPool(troops) -- troops MUST be a table
|
|||||||
end
|
end
|
||||||
if not troops.orders then troops.orders = "guard" end
|
if not troops.orders then troops.orders = "guard" end
|
||||||
troops.orders = troops.orders:lower()
|
troops.orders = troops.orders:lower()
|
||||||
|
if not troops.moveFormation then troops.moveFormation = "Custom" end
|
||||||
troops.reschedule = true -- in case we use scheduled update
|
troops.reschedule = true -- in case we use scheduled update
|
||||||
-- we now add to internal array. this is worked on by all
|
-- we now add to internal array. this is worked on by all
|
||||||
-- update meths, on scheduled upadtes, it is only used to
|
-- update meths, on scheduled upadtes, it is only used to
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cfxHeloTroops = {}
|
cfxHeloTroops = {}
|
||||||
cfxHeloTroops.version = "3.0.3"
|
cfxHeloTroops.version = "3.0.4"
|
||||||
cfxHeloTroops.verbose = false
|
cfxHeloTroops.verbose = false
|
||||||
cfxHeloTroops.autoDrop = true
|
cfxHeloTroops.autoDrop = true
|
||||||
cfxHeloTroops.autoPickup = false
|
cfxHeloTroops.autoPickup = false
|
||||||
@ -40,6 +40,7 @@ cfxHeloTroops.requestRange = 500 -- meters
|
|||||||
3.0.1 - fixed a bug with legalTroops attribute
|
3.0.1 - fixed a bug with legalTroops attribute
|
||||||
3.0.2 - fixed a typo in in-air menu
|
3.0.2 - fixed a typo in in-air menu
|
||||||
3.0.3 - pointInZone check for insertion rather than radius
|
3.0.3 - pointInZone check for insertion rather than radius
|
||||||
|
3.0.4 - also handles picking up troops with orders "captureandhold"
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
--
|
--
|
||||||
@ -52,8 +53,6 @@ cfxHeloTroops.requestRange = 500 -- meters
|
|||||||
|
|
||||||
cfxHeloTroops.requiredLibs = {
|
cfxHeloTroops.requiredLibs = {
|
||||||
"dcsCommon", -- common is of course needed for everything
|
"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
|
"cfxZones", -- Zones, of course
|
||||||
"cfxCommander", -- to make troops do stuff
|
"cfxCommander", -- to make troops do stuff
|
||||||
"cfxGroundTroops", -- generic when dropping troops
|
"cfxGroundTroops", -- generic when dropping troops
|
||||||
@ -641,6 +640,7 @@ function cfxHeloTroops.deployTroopsFromHelicopter(conf)
|
|||||||
local orders = conf.troopsOnBoard.orders
|
local orders = conf.troopsOnBoard.orders
|
||||||
local dest = conf.troopsOnBoard.destination
|
local dest = conf.troopsOnBoard.destination
|
||||||
local theName = conf.troopsOnBoard.name
|
local theName = conf.troopsOnBoard.name
|
||||||
|
local moveFormation = conf.troopsOnBoard.moveFormation
|
||||||
|
|
||||||
if not orders then orders = "guard" end
|
if not orders then orders = "guard" end
|
||||||
|
|
||||||
@ -670,7 +670,15 @@ function cfxHeloTroops.deployTroopsFromHelicopter(conf)
|
|||||||
troopData.destination = dest -- only for attackzone orders
|
troopData.destination = dest -- only for attackzone orders
|
||||||
cfxHeloTroops.deployedTroops[theData.name] = troopData
|
cfxHeloTroops.deployedTroops[theData.name] = troopData
|
||||||
|
|
||||||
local troop = cfxGroundTroops.createGroundTroops(theGroup, range, orders)
|
local troop = cfxGroundTroops.createGroundTroops(theGroup, range, orders, moveFormation)
|
||||||
|
if orders == "captureandhold" then
|
||||||
|
-- we get the target zone NOW!!! before we flip the zone and
|
||||||
|
-- and make them run to the wrong zone
|
||||||
|
dest = cfxGroundTroops.getClosestEnemyZone(troop)
|
||||||
|
troopData.destination = dest
|
||||||
|
trigger.action.outText("Inserting troops to capture zone <" .. dest.name .. ">", 30)
|
||||||
|
end
|
||||||
|
|
||||||
troop.destination = dest -- transfer target zone for attackzone oders
|
troop.destination = dest -- transfer target zone for attackzone oders
|
||||||
cfxGroundTroops.addGroundTroopsToPool(troop) -- will schedule move orders
|
cfxGroundTroops.addGroundTroopsToPool(troop) -- will schedule move orders
|
||||||
trigger.action.outTextForGroup(conf.id, "<" .. theGroup:getName() .. "> have deployed to the ground with orders " .. orders .. "!", 30)
|
trigger.action.outTextForGroup(conf.id, "<" .. theGroup:getName() .. "> have deployed to the ground with orders " .. orders .. "!", 30)
|
||||||
@ -735,8 +743,13 @@ function cfxHeloTroops.doLoadGroup(args)
|
|||||||
conf.troopsOnBoard.orders = pooledGroup.orders
|
conf.troopsOnBoard.orders = pooledGroup.orders
|
||||||
conf.troopsOnBoard.range = pooledGroup.range
|
conf.troopsOnBoard.range = pooledGroup.range
|
||||||
conf.troopsOnBoard.destination = pooledGroup.destination -- may be nil
|
conf.troopsOnBoard.destination = pooledGroup.destination -- may be nil
|
||||||
|
conf.troopsOnBoard.moveFormation = pooledGroup.moveFormation
|
||||||
|
if pooledGroup.orders and pooledGroup.orders == "captureandhold" then
|
||||||
|
conf.troopsOnBoard.destination = nil -- forget last destination so they can be helo-redeployed
|
||||||
|
end
|
||||||
cfxGroundTroops.removeTroopsFromPool(pooledGroup)
|
cfxGroundTroops.removeTroopsFromPool(pooledGroup)
|
||||||
trigger.action.outTextForGroup(conf.id, "Team '".. conf.troopsOnBoard.name .."' loaded and has orders <" .. conf.troopsOnBoard.orders .. ">", 30)
|
trigger.action.outTextForGroup(conf.id, "Team '".. conf.troopsOnBoard.name .."' loaded and has orders <" .. conf.troopsOnBoard.orders .. ">", 30)
|
||||||
|
-- trigger.action.outText("and mf = <" .. conf.troopsOnBoard.moveFormation .. ">", 30)
|
||||||
--trigger.action.outSoundForGroup(conf.id, cfxHeloTroops.actionSound) -- "Quest Snare 3.wav")
|
--trigger.action.outSoundForGroup(conf.id, cfxHeloTroops.actionSound) -- "Quest Snare 3.wav")
|
||||||
else
|
else
|
||||||
if cfxHeloTroops.verbose then
|
if cfxHeloTroops.verbose then
|
||||||
|
|||||||
@ -65,10 +65,12 @@ function income.update()
|
|||||||
has, balance = bank.getBalance(1)
|
has, balance = bank.getBalance(1)
|
||||||
tick = string.gsub(income.tickMessage, "<i>", redI)
|
tick = string.gsub(income.tickMessage, "<i>", redI)
|
||||||
trigger.action.outTextForCoalition(1, "\n" .. tick .. "\nNew balance: §" .. balance .. "\n", 30)
|
trigger.action.outTextForCoalition(1, "\n" .. tick .. "\nNew balance: §" .. balance .. "\n", 30)
|
||||||
|
trigger.action.outSoundForCoalition(1, income.reportSound)
|
||||||
|
|
||||||
has, balance = bank.getBalance(2)
|
has, balance = bank.getBalance(2)
|
||||||
tick = string.gsub(income.tickMessage, "<i>", blueI)
|
tick = string.gsub(income.tickMessage, "<i>", blueI)
|
||||||
trigger.action.outTextForCoalition(2, "\n" .. tick .. "\nNew balance: §" .. balance .. "\n", 30)
|
trigger.action.outTextForCoalition(2, "\n" .. tick .. "\nNew balance: §" .. balance .. "\n", 30)
|
||||||
|
trigger.action.outSoundForCoalition(2, income.reportSound)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -88,6 +90,8 @@ function income.readConfigZone()
|
|||||||
income.interval = theZone:getNumberFromZoneProperty("interval", 10 * 60) -- every 10 minutes
|
income.interval = theZone:getNumberFromZoneProperty("interval", 10 * 60) -- every 10 minutes
|
||||||
income.tickMessage = theZone:getStringFromZoneProperty("tickMessage", "New funds from income available: §<i>")
|
income.tickMessage = theZone:getStringFromZoneProperty("tickMessage", "New funds from income available: §<i>")
|
||||||
income.announceTicks = theZone:getBoolFromZoneProperty("announceTicks", true)
|
income.announceTicks = theZone:getBoolFromZoneProperty("announceTicks", true)
|
||||||
|
income.reportSound = theZone:getStringFromZoneProperty("reportSound", "<none>")
|
||||||
|
|
||||||
income.verbose = theZone.verbose
|
income.verbose = theZone.verbose
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
254
modules/launchPlatform.lua
Normal file
254
modules/launchPlatform.lua
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
launchPlatform = {}
|
||||||
|
launchPlatform.version = "0.0.0"
|
||||||
|
launchPlatform.requiredLibs = {
|
||||||
|
"dcsCommon",
|
||||||
|
"cfxZones",
|
||||||
|
}
|
||||||
|
launchPlatform.zones = {}
|
||||||
|
launchPlatform.redLaunchers = {}
|
||||||
|
launchPlatform.blueLaunchers = {}
|
||||||
|
|
||||||
|
-- weapon types currently known
|
||||||
|
-- 52613349374 = tomahawk
|
||||||
|
|
||||||
|
function launchPlatform.addLaunchPlatform(theZone)
|
||||||
|
launchPlatform.zones[theZone.name] = theZone
|
||||||
|
if theZone.coa == 1 or theZone.coa == 0 then
|
||||||
|
launchPlatform.redLaunchers[theZone.name] = theZone
|
||||||
|
end
|
||||||
|
if theZone.coa == 2 or theZone.coa == 0 then
|
||||||
|
launchPlatform.blueLaunchers[theZone.name] = theZone
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function launchPlatform.readLaunchPlatform(theZone)
|
||||||
|
theZone.coa = theZone:getCoalitionFromZoneProperty("coalition", 0)
|
||||||
|
theZone.impactRadius = theZone:getNumberFromZoneProperty("radius", 1000)
|
||||||
|
if theZone:hasProperty("salvos") then
|
||||||
|
theZone.num = theZone:getNumberFromZoneProperty("salvos", 1)
|
||||||
|
end
|
||||||
|
if theZone:hasProperty("salvo") then
|
||||||
|
theZone.num = theZone:getNumberFromZoneProperty("salvo", 1)
|
||||||
|
end
|
||||||
|
-- possible extensions: missile. currently tomahawk launched from a missile cruiser that beams in and vanishes later
|
||||||
|
-- later versions could support SCUDS and some long-range arty,
|
||||||
|
-- perhaps even aircraft
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- note - the tomahawks don't care who they belong to, we do not
|
||||||
|
-- need them to belong to anyone, it may be a visibility thing though
|
||||||
|
|
||||||
|
function launchPlatform.launchForPlatform(coa, theZone, tgtPoint, tgtZone)
|
||||||
|
local launchPoint = theZone:createRandomPointInZone()
|
||||||
|
local gData = launchPlatform.createData(launchPoint, tgtPoint, tgtZone, theZone.impactRadius, theZone.name, theZone.num)
|
||||||
|
return gData
|
||||||
|
end
|
||||||
|
|
||||||
|
function launchPlatform.launchAtTargetZone(coa, tgtZone, theType) -- gets closest platform for target
|
||||||
|
-- type currently not supported
|
||||||
|
local platforms = launchPlatform.redLaunchers
|
||||||
|
if coa == 2 then platforms = launchPlatform.blueLaunchers end
|
||||||
|
local cty = dcsCommon.getACountryForCoalition(coa)
|
||||||
|
|
||||||
|
-- get closest launcher for target
|
||||||
|
local tgtPoint = tgtZone:getPoint()
|
||||||
|
local src, dist = cfxZones.getClosestZone(tgtPoint, platforms)
|
||||||
|
trigger.action.outText("+++LP: chosen <" .. src.name .. "> as launch platform", 30)
|
||||||
|
|
||||||
|
local theLauncher = launchPlatform.launchForPlatform(coa, src, tgtPoint, tgtZone)
|
||||||
|
if not theLauncher then
|
||||||
|
trigger.action.outText("NO LAUNCHER", 30)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
-- if type is tomahawk, the platform is ship = 3
|
||||||
|
local theGroup = coalition.addGroup(cty, 3, theLauncher)
|
||||||
|
if not theGroup then
|
||||||
|
trigger.action.outText("!!!!!!!!!!!!!NOPE", 30)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- we remove the group in some time
|
||||||
|
local now = timer.getTime()
|
||||||
|
timer.scheduleFunction(launchPlatform.asynchRemovePlatform, theGroup:getName(), now + 300)
|
||||||
|
end
|
||||||
|
|
||||||
|
function launchPlatform.asynchRemovePlatform(args)
|
||||||
|
trigger.action.outText("LP: asynch remove for group <" .. args .. ">", 30)
|
||||||
|
local theGroup = Group.getByName(args)
|
||||||
|
if not theGroup then return end
|
||||||
|
Group.destroy(theGroup)
|
||||||
|
end
|
||||||
|
|
||||||
|
function launchPlatform.createData(thePoint, theTarget, targetZone, radius, name, num, wType)
|
||||||
|
-- if present, we can use targetZone with some intelligence
|
||||||
|
if not thePoint then
|
||||||
|
trigger.action.outText("NO POINT", 30)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if not theTarget then
|
||||||
|
trigger.action.outText("NO TARGET", 30)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if not wType then wType = 52613349374 end
|
||||||
|
if not radius then radius = 1000 end
|
||||||
|
local useQty = true
|
||||||
|
if not num then num = 15 end
|
||||||
|
if num > 30 then num = 30 end -- max 30 missiles
|
||||||
|
|
||||||
|
if not name then name = "launcherDML" end
|
||||||
|
local gData = {
|
||||||
|
["visible"] = false,
|
||||||
|
["tasks"] = {},
|
||||||
|
["uncontrollable"] = false,
|
||||||
|
["route"] = {
|
||||||
|
["points"] = {
|
||||||
|
[1] = {
|
||||||
|
["alt"] = 0,
|
||||||
|
["type"] = "Turning Point",
|
||||||
|
["ETA"] = 0,
|
||||||
|
["alt_type"] = "BARO",
|
||||||
|
["formation_template"] = "",
|
||||||
|
["y"] = thePoint.z,
|
||||||
|
["x"] = thePoint.x,
|
||||||
|
["ETA_locked"] = true,
|
||||||
|
["speed"] = 0,
|
||||||
|
["action"] = "Turning Point",
|
||||||
|
["task"] = {
|
||||||
|
["id"] = "ComboTask",
|
||||||
|
["params"] = {
|
||||||
|
["tasks"] = {
|
||||||
|
[1] = {
|
||||||
|
["number"] = 1,
|
||||||
|
["auto"] = false,
|
||||||
|
["id"] = "FireAtPoint",
|
||||||
|
["enabled"] = true,
|
||||||
|
["params"] = {
|
||||||
|
["y"] = theTarget.z,
|
||||||
|
["x"] = theTarget.x,
|
||||||
|
["expendQtyEnabled"] = true,
|
||||||
|
["alt_type"] = 1,
|
||||||
|
["templateId"] = "",
|
||||||
|
["expendQty"] = 2,
|
||||||
|
["weaponType"] = wType,
|
||||||
|
["zoneRadius"] = radius,
|
||||||
|
}, -- end of ["params"]
|
||||||
|
}, -- end of [1]
|
||||||
|
}, -- end of ["tasks"]
|
||||||
|
}, -- end of ["params"]
|
||||||
|
}, -- end of ["task"]
|
||||||
|
["speed_locked"] = true,
|
||||||
|
}, -- end of [1]
|
||||||
|
}, -- end of ["points"]
|
||||||
|
}, -- end of ["route"]
|
||||||
|
["hidden"] = false,
|
||||||
|
["units"] = {
|
||||||
|
[1] = {
|
||||||
|
["modulation"] = 0,
|
||||||
|
["skill"] = "Average",
|
||||||
|
["type"] = "USS_Arleigh_Burke_IIa",
|
||||||
|
["y"] = thePoint.z,
|
||||||
|
["x"] = thePoint.x,
|
||||||
|
["name"] = dcsCommon.uuid(name),
|
||||||
|
["heading"] = 2.2925180610373,
|
||||||
|
["frequency"] = 127500000,
|
||||||
|
}, -- end of [1]
|
||||||
|
}, -- end of ["units"]
|
||||||
|
["y"] = thePoint.z,
|
||||||
|
["x"] = thePoint.x,
|
||||||
|
["name"] = dcsCommon.uuid(name),
|
||||||
|
["start_time"] = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- now create the tasks block replacements
|
||||||
|
-- create random target locations inside
|
||||||
|
-- target point with radius and launch 2 per salvo
|
||||||
|
-- perhaps add some inteligence to target resource points
|
||||||
|
-- if inside camp
|
||||||
|
local hiPrioTargets
|
||||||
|
if targetZone and targetZone.cloners and #targetZone.cloners > 0 then
|
||||||
|
trigger.action.outText("+++LP: detected <" .. targetZone.name .. "> is camp with <" .. #targetZone.cloners .. "> res-points, re-targeting hi-prio", 30)
|
||||||
|
hiPrioTargets = targetZone.cloners
|
||||||
|
radius = radius / 10 -- much smaller error
|
||||||
|
end
|
||||||
|
local tasks = {}
|
||||||
|
for i=1, num do
|
||||||
|
local dp = dcsCommon.randomPointInCircle(radius, 0)
|
||||||
|
if hiPrioTargets then
|
||||||
|
-- choose one of the
|
||||||
|
local thisCloner = dcsCommon.pickRandom(hiPrioTargets)
|
||||||
|
local tp = thisCloner:getPoint()
|
||||||
|
dp.x = dp.x + tp.x
|
||||||
|
dp.z = dp.z + tp.z
|
||||||
|
|
||||||
|
else
|
||||||
|
dp.x = dp.x + theTarget.x
|
||||||
|
dp.z = dp.z + theTarget.z
|
||||||
|
end
|
||||||
|
local telem = {
|
||||||
|
["number"] = i,
|
||||||
|
["auto"] = false,
|
||||||
|
["id"] = "FireAtPoint",
|
||||||
|
["enabled"] = true,
|
||||||
|
["params"] = {
|
||||||
|
["y"] = dp.z,
|
||||||
|
["x"] = dp.x,
|
||||||
|
["expendQtyEnabled"] = true,
|
||||||
|
["alt_type"] = 1,
|
||||||
|
["templateId"] = "",
|
||||||
|
["expendQty"] = 1,
|
||||||
|
["weaponType"] = wType,
|
||||||
|
["zoneRadius"] = radius,
|
||||||
|
}, -- end of ["params"]
|
||||||
|
} -- end of [1]
|
||||||
|
-- table.insert(tasks, telem)
|
||||||
|
tasks[i] = telem
|
||||||
|
end
|
||||||
|
|
||||||
|
-- now replace old task with new
|
||||||
|
gData.route.points[1].task.params.tasks = tasks
|
||||||
|
return gData
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- start up
|
||||||
|
--
|
||||||
|
function launchPlatform.readConfigZone()
|
||||||
|
local theZone = cfxZones.getZoneByName("launchPlatformConfig")
|
||||||
|
if not theZone then
|
||||||
|
theZone = cfxZones.createSimpleZone("launchPlatformConfig")
|
||||||
|
end
|
||||||
|
launchPlatform.verbose = theZone.verbose
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function launchPlatform.start()
|
||||||
|
-- lib check
|
||||||
|
if not dcsCommon.libCheck then
|
||||||
|
trigger.action.outText("cfx launchPlatform requires dcsCommon", 30)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if not dcsCommon.libCheck("cfx launchPlatform", launchPlatform.requiredLibs) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- read config
|
||||||
|
launchPlatform.readConfigZone()
|
||||||
|
|
||||||
|
-- process launchPlatform Zones
|
||||||
|
local attrZones = cfxZones.getZonesWithAttributeNamed("launchPlatform")
|
||||||
|
for k, aZone in pairs(attrZones) do
|
||||||
|
launchPlatform.readLaunchPlatform(aZone) -- process attributes
|
||||||
|
launchPlatform.addLaunchPlatform(aZone) -- add to list
|
||||||
|
end
|
||||||
|
|
||||||
|
-- say hi
|
||||||
|
trigger.action.outText("launchPlatform v" .. launchPlatform.version .. " started.", 30)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if not launchPlatform.start() then
|
||||||
|
trigger.action.outText("launchPlatform failed to start.", 30)
|
||||||
|
launchPlatform = nil
|
||||||
|
end
|
||||||
@ -678,7 +678,9 @@ end
|
|||||||
|
|
||||||
function milHelo.GCcollected(gName)
|
function milHelo.GCcollected(gName)
|
||||||
-- do some housekeeping?
|
-- do some housekeeping?
|
||||||
trigger.action.outText("removed flight <" .. gName .. ">", 30)
|
if milHelo.verbose then
|
||||||
|
trigger.action.outText("removed flight <" .. gName .. ">", 30)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function milHelo.GC()
|
function milHelo.GC()
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
noGap = {}
|
noGap = {}
|
||||||
noGap.version = "1.0.0"
|
noGap.version = "1.0.1"
|
||||||
|
|
||||||
noGap.verbose = false
|
noGap.verbose = false
|
||||||
noGap.ignoreMe = "-ng" -- ignore altogether
|
noGap.ignoreMe = "-ng" -- ignore altogether
|
||||||
@ -37,6 +37,7 @@ noGap.requiredLibs = {
|
|||||||
|
|
||||||
Version History
|
Version History
|
||||||
1.0.0 - Initial version
|
1.0.0 - Initial version
|
||||||
|
1.0.1 - added "from runway"
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
@ -80,6 +81,7 @@ function noGap.isGroundStart(theGroup)
|
|||||||
if action == "Fly Over Point" then return false end
|
if action == "Fly Over Point" then return false end
|
||||||
if action == "Turning Point" then return false end
|
if action == "Turning Point" then return false end
|
||||||
if action == "Landing" then return false end
|
if action == "Landing" then return false end
|
||||||
|
if action == "From Runway" then return false end
|
||||||
-- aircraft is on the ground - but is it in water (carrier)?
|
-- aircraft is on the ground - but is it in water (carrier)?
|
||||||
local u1 = theGroup.units[1]
|
local u1 = theGroup.units[1]
|
||||||
local sType = land.getSurfaceType(u1) -- has fields x and y
|
local sType = land.getSurfaceType(u1) -- has fields x and y
|
||||||
|
|||||||
74
modules/slotty.lua
Normal file
74
modules/slotty.lua
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
slotty = {}
|
||||||
|
slotty.version = "1.1.0"
|
||||||
|
--[[--
|
||||||
|
Single-player slot blocking and slot blocking fallback
|
||||||
|
for multiplayer when SSB is not installed on server.
|
||||||
|
Uses SSB's method of marking groups with flags
|
||||||
|
(c) 2024 by Christian Franz
|
||||||
|
|
||||||
|
Slotty can be disabled by setting the value of the flag named "noSlotty" to
|
||||||
|
a value greater than zero
|
||||||
|
|
||||||
|
Version history
|
||||||
|
1.0.0 - Initial version
|
||||||
|
1.1.0 - "noSlotty" global disable flag, anti-mirror SSB flag
|
||||||
|
|
||||||
|
--]]--
|
||||||
|
|
||||||
|
function slotty:onEvent(event)
|
||||||
|
if not event.initiator then return end
|
||||||
|
local theUnit = event.initiator
|
||||||
|
if not theUnit.getPlayerName then return end
|
||||||
|
local pName = theUnit:getPlayerName()
|
||||||
|
if not pName then return end
|
||||||
|
local uName = theUnit:getName()
|
||||||
|
local theGroup = theUnit:getGroup()
|
||||||
|
local gName = theGroup:getName()
|
||||||
|
if event.id == 15 then -- birth
|
||||||
|
if trigger.misc.getUserFlag("noSlotty") > 0 then return end
|
||||||
|
local np = net.get_player_list() -- retruns a list of PID
|
||||||
|
local isSP = false
|
||||||
|
if not np or (#np < 1) then
|
||||||
|
isSP = true -- we are in single-player mode
|
||||||
|
end
|
||||||
|
-- now see if that group name is currently blocked
|
||||||
|
local blockstate = false
|
||||||
|
if trigger.misc.getUserFlag(gName) > 0 then
|
||||||
|
trigger.action.outText("Group <" .. gName .. "> is currently blocked and can't be entered", 30)
|
||||||
|
blockstate = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if not blockstate then return end -- nothing left to do, all is fine
|
||||||
|
|
||||||
|
-- interface with SSBClient for compatibility
|
||||||
|
if cfxSSBClient and cfxSSBClient.occupiedUnits then
|
||||||
|
cfxSSBClient.occupiedUnits[uName] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if isSP then
|
||||||
|
theUnit:destroy() -- SP kill, works only in Single-player
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- we would leave the rest to SSB, but if we get here, SSB is
|
||||||
|
-- not installed on host, so we proceed with invoking netAPI
|
||||||
|
for idx,pid in pairs(np) do
|
||||||
|
local netName = net.get_name(pid)
|
||||||
|
if netName == pName then
|
||||||
|
timer.scheduleFunction(slotty.kick, pid, timer.getTime() + 0.1)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function slotty.kick(pid)
|
||||||
|
net.force_player_slot(pid, 0, '') -- '', thanks Dz!
|
||||||
|
end
|
||||||
|
|
||||||
|
function slotty.start()
|
||||||
|
world.addEventHandler(slotty)
|
||||||
|
trigger.action.outText("slotty v " .. slotty.version .. " running.", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
slotty.start()
|
||||||
@ -1,5 +1,5 @@
|
|||||||
cfxSpawnZones = {}
|
cfxSpawnZones = {}
|
||||||
cfxSpawnZones.version = "2.0.1"
|
cfxSpawnZones.version = "2.0.2"
|
||||||
cfxSpawnZones.requiredLibs = {
|
cfxSpawnZones.requiredLibs = {
|
||||||
"dcsCommon", -- common is of course needed for everything
|
"dcsCommon", -- common is of course needed for everything
|
||||||
-- pretty stupid to check for this since we
|
-- pretty stupid to check for this since we
|
||||||
@ -27,6 +27,8 @@ cfxSpawnZones.spawnedGroups = {}
|
|||||||
- baseName defaults to zone name, as it is safe for naming
|
- baseName defaults to zone name, as it is safe for naming
|
||||||
- spawnWithSpawner direct link in spawner to spawnZones
|
- spawnWithSpawner direct link in spawner to spawnZones
|
||||||
2.0.1 - fix in verifySpawnOwnership() when not master zone found
|
2.0.1 - fix in verifySpawnOwnership() when not master zone found
|
||||||
|
2.0.2 - new "moveFormation" attribute
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
cfxSpawnZones.allSpawners = {}
|
cfxSpawnZones.allSpawners = {}
|
||||||
@ -128,6 +130,13 @@ function cfxSpawnZones.createSpawner(inZone)
|
|||||||
theSpawner.count = 1 -- used to create names, and count how many groups created
|
theSpawner.count = 1 -- used to create names, and count how many groups created
|
||||||
theSpawner.theSpawn = nil -- link to last spawned group
|
theSpawner.theSpawn = nil -- link to last spawned group
|
||||||
theSpawner.formation = inZone:getStringFromZoneProperty("formation", "circle_out")
|
theSpawner.formation = inZone:getStringFromZoneProperty("formation", "circle_out")
|
||||||
|
theSpawner.moveFormation = inZone:getStringFromZoneProperty("moveFormation", "Custom")
|
||||||
|
|
||||||
|
if theSpawner.moveFormation == "Custom" or theSpawner.moveFormation == "EchelonR" or theSpawner.moveFormation == "EchelonL" or theSpawner.moveFormation == "Diamond" or theSpawner.moveFormation == "Vee" or theSpawner.moveFormation == "Cone" or theSpawner.moveFormation == "Rank" then -- all fine, do nothing
|
||||||
|
else
|
||||||
|
trigger.action.outText("+++SpwZ: unknown moveFormation <" .. theSpawner.moveFormation .. "> in spawn zone <" .. inZone.name .. ">, defaulting to 'Custom'", 30)
|
||||||
|
theSpawner.moveFormation = "Custom"
|
||||||
|
end
|
||||||
theSpawner.paused = inZone:getBoolFromZoneProperty("paused", false)
|
theSpawner.paused = inZone:getBoolFromZoneProperty("paused", false)
|
||||||
-- orders are always converted to all lower case
|
-- orders are always converted to all lower case
|
||||||
theSpawner.orders = inZone:getStringFromZoneProperty("orders", "guard"):lower()
|
theSpawner.orders = inZone:getStringFromZoneProperty("orders", "guard"):lower()
|
||||||
@ -297,6 +306,7 @@ function cfxSpawnZones.spawnWithSpawner(aSpawner)
|
|||||||
troopData.groupData = theData
|
troopData.groupData = theData
|
||||||
troopData.orders = aSpawner.orders -- always set
|
troopData.orders = aSpawner.orders -- always set
|
||||||
troopData.side = theCoalition
|
troopData.side = theCoalition
|
||||||
|
troopData.moveFormation = aSpawner.moveFormation
|
||||||
troopData.target = aSpawner.target -- can be nil!
|
troopData.target = aSpawner.target -- can be nil!
|
||||||
troopData.tracker = theZone.trackWith -- taken from ZONE!!, can be nil
|
troopData.tracker = theZone.trackWith -- taken from ZONE!!, can be nil
|
||||||
troopData.range = aSpawner.range
|
troopData.range = aSpawner.range
|
||||||
@ -318,7 +328,7 @@ function cfxSpawnZones.spawnWithSpawner(aSpawner)
|
|||||||
AI.Option.Ground.val.ROE.WEAPON_HOLD,
|
AI.Option.Ground.val.ROE.WEAPON_HOLD,
|
||||||
1.0)
|
1.0)
|
||||||
else
|
else
|
||||||
local newTroops = cfxGroundTroops.createGroundTroops(theGroup, aSpawner.range, aSpawner.orders)
|
local newTroops = cfxGroundTroops.createGroundTroops(theGroup, aSpawner.range, aSpawner.orders, aSpawner.moveFormation)
|
||||||
cfxGroundTroops.addGroundTroopsToPool(newTroops)
|
cfxGroundTroops.addGroundTroopsToPool(newTroops)
|
||||||
|
|
||||||
-- see if we have defined a target zone as destination
|
-- see if we have defined a target zone as destination
|
||||||
@ -576,6 +586,7 @@ function cfxSpawnZones.loadData()
|
|||||||
for gName, gdTroop in pairs (allTroopData) do
|
for gName, gdTroop in pairs (allTroopData) do
|
||||||
local gData = gdTroop.groupData
|
local gData = gdTroop.groupData
|
||||||
local orders = gdTroop.orders
|
local orders = gdTroop.orders
|
||||||
|
local moveFormation = gdTroop.moveFormation
|
||||||
local target = gdTroop.target
|
local target = gdTroop.target
|
||||||
local tracker = gdTroop.tracker
|
local tracker = gdTroop.tracker
|
||||||
local side = gdTroop.side
|
local side = gdTroop.side
|
||||||
@ -598,7 +609,7 @@ function cfxSpawnZones.loadData()
|
|||||||
1.0)
|
1.0)
|
||||||
else
|
else
|
||||||
-- add to groundTroops
|
-- add to groundTroops
|
||||||
local newTroops = cfxGroundTroops.createGroundTroops(theGroup, range, orders)
|
local newTroops = cfxGroundTroops.createGroundTroops(theGroup, range, orders, moveFormation)
|
||||||
cfxGroundTroops.addGroundTroopsToPool(newTroops)
|
cfxGroundTroops.addGroundTroopsToPool(newTroops)
|
||||||
-- engage a target zone
|
-- engage a target zone
|
||||||
if target then
|
if target then
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
-- theDebugger 2.x
|
-- theDebugger 2.x
|
||||||
debugger = {}
|
debugger = {}
|
||||||
debugger.version = "2.1.0"
|
debugger.version = "2.1.1"
|
||||||
debugDemon = {}
|
debugDemon = {}
|
||||||
debugDemon.version = "2.1.0"
|
debugDemon.version = "2.1.0"
|
||||||
|
|
||||||
@ -39,6 +39,7 @@ debugger.log = ""
|
|||||||
debug invocation on clone of data structure
|
debug invocation on clone of data structure
|
||||||
readback verification of flag set
|
readback verification of flag set
|
||||||
fixed getProperty() in debugger with zone
|
fixed getProperty() in debugger with zone
|
||||||
|
2.1.1 - removed bug that skipped events? when zone not verbose
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
@ -267,11 +268,13 @@ function debugger.createEventMonWithZone(theZone)
|
|||||||
end
|
end
|
||||||
for idx, aFlag in pairs(flagArray) do
|
for idx, aFlag in pairs(flagArray) do
|
||||||
local evt = tonumber(aFlag)
|
local evt = tonumber(aFlag)
|
||||||
if evt and (debugger.verbose or theZone.verbose) then
|
if evt then
|
||||||
if evt < 0 then evt = 0 end
|
if evt < 0 then evt = 0 end
|
||||||
if evt > 57 then evt = 57 end
|
if evt > 57 then evt = 57 end
|
||||||
debugger.showEvents[evt] = debugDemon.eventList[tostring(evt)]
|
debugger.showEvents[evt] = debugDemon.eventList[tostring(evt)]
|
||||||
debugger.outText(" monitoring event <" .. debugger.showEvents[evt] .. ">", 30)
|
if (debugger.verbose or theZone.verbose) then
|
||||||
|
debugger.outText(" monitoring event <" .. debugger.showEvents[evt] .. ">", 30)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
unitPersistence = {}
|
unitPersistence = {}
|
||||||
unitPersistence.version = '2.0.0'
|
unitPersistence.version = '2.0.1'
|
||||||
unitPersistence.verbose = false
|
unitPersistence.verbose = false
|
||||||
unitPersistence.updateTime = 60 -- seconds. Once every minute check statics
|
unitPersistence.updateTime = 60 -- seconds. Once every minute check statics
|
||||||
unitPersistence.requiredLibs = {
|
unitPersistence.requiredLibs = {
|
||||||
@ -21,6 +21,7 @@ unitPersistence.requiredLibs = {
|
|||||||
- fixed air spawn (fixed wing)
|
- fixed air spawn (fixed wing)
|
||||||
2.0.0 - dmlZones, OOP
|
2.0.0 - dmlZones, OOP
|
||||||
cleanup
|
cleanup
|
||||||
|
2.0.1 - cosmetic verbosity during save
|
||||||
|
|
||||||
REQUIRES PERSISTENCE AND MX
|
REQUIRES PERSISTENCE AND MX
|
||||||
|
|
||||||
@ -162,7 +163,9 @@ function unitPersistence.saveData()
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
theUnitData.isDead = true
|
theUnitData.isDead = true
|
||||||
trigger.action.outText("+++unitPersistence - unit <" .. uName .. "> of group <" .. groupName .. "> is dead or non-existant", 30)
|
if unitPersistence.verbose then
|
||||||
|
trigger.action.outText("+++unitPersistence - unit <" .. uName .. "> of group <" .. groupName .. "> is dead or non-existant", 30)
|
||||||
|
end
|
||||||
end -- is alive and exists?
|
end -- is alive and exists?
|
||||||
end -- unit maybe not dead
|
end -- unit maybe not dead
|
||||||
end -- iterate units in group
|
end -- iterate units in group
|
||||||
|
|||||||
Binary file not shown.
BIN
tutorial & demo missions/demo - non SSB & SP slot blocking.miz
Normal file
BIN
tutorial & demo missions/demo - non SSB & SP slot blocking.miz
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user