该DCS脚本可以对选定群组的飞机进行死亡后复活或者使用F10更换飞机、手动重置选定的地面目标。
前置:
需要提前安装DCS的MIST框架
1.克隆仓库:
https://github.com/mrSkortch/MissionScriptingTools.git
2.导入项目 将克隆下来的项目文件夹放置在 DCS 的脚本目录中。
MissionScriptingTools(简称 Mist)是一个为Digital Combat Simulator(DCS)设计的脚本工具集合。该项目旨在为 DCS 的脚本引擎提供额外的功能和数据库,以简化常见的脚本任务和挑战。Mist 包含了一系列的 Lua 函数和数据库,使得任务脚本编写更加高效和便捷。
-- 定义可选的飞机类型和对应的模板群组名称
local aircraftOptions = {
["JF-17"] = "pve-1", -- pve-1 为飞机的群组
["Su-27"] = "pve-2",
["FA-18"] = "pve-3",
["F-16C"] = "pve-4",
["F-15C"] = "pve-5"
}
-- 定义需要重置的地面目标群组
local groupsToReset = {"地面-29", "地面-30", "地面-31"} --改为你地图种真实的地面目标
-- 状态管理
local systemState = {
currentAircraft = "F-15C", --默认的群组
currentTemplate = aircraftOptions["F-15C"],
activeGroupName = nil,
isGroupAlive = false,
isSpawning = false,
pendingOperations = {},
templateStates = {} -- 跟踪每个模板的状态
}
-- 初始化模板状态跟踪
for aircraftType, templateName in pairs(aircraftOptions) do
systemState.templateStates[templateName] = {
lastActive = nil,
isTemplateActive = false,
spawnCount = 0
}
end
-- 检查MIST框架可用性
local function isMISTAvailable()
return mist and mist.respawnGroup
end
-- 群组存在性检查
local function isGroupActive(groupName)
if not groupName then
return false
end
local group = Group.getByName(groupName)
return group and group:isExist()
end
-- 模板验证与恢复函数
local function validateAndRecoverTemplate(templateName)
if not templateName then
env.error("模板验证: 模板名称为空")
return false
end
-- 检查模板是否存在
local templateGroup = Group.getByName(templateName)
if not templateGroup then
env.warning("模板不存在: " .. templateName)
-- 尝试通过MIST恢复模板
if isMISTAvailable() then
env.info("尝试通过MIST恢复模板: " .. templateName)
local success, result = pcall(function()
return mist.respawnGroup(templateName, true)
end)
if success then
env.info("MIST模板恢复成功: " .. templateName)
-- 延迟验证恢复结果
timer.scheduleFunction(function()
local restoredGroup = Group.getByName(templateName)
if restoredGroup then
systemState.templateStates[templateName].isTemplateActive = true
env.info("模板恢复验证成功: " .. templateName)
return true
else
env.warning("模板恢复验证失败: " .. templateName)
return false
end
end, nil, timer.getTime() + 3)
return true
else
env.error("MIST模板恢复失败: " .. tostring(result))
return false
end
else
env.error("MIST框架不可用,无法恢复模板: " .. templateName)
return false
end
end
-- 模板存在,验证其状态
if templateGroup:isExist() then
systemState.templateStates[templateName].isTemplateActive = true
env.info("模板状态正常: " .. templateName)
return true
else
env.warning("模板存在但不可用: " .. templateName)
systemState.templateStates[templateName].isTemplateActive = false
return false
end
end
-- 安全群组复制与激活
local function safeCloneAndActivateGroup()
if systemState.isSpawning then
env.info("生成操作正在进行中,跳过重复请求")
return false
end
systemState.isSpawning = true
-- 验证MIST框架
if not isMISTAvailable() then
trigger.action.outText("错误:MIST框架未加载", 10)
systemState.isSpawning = false
return false
end
local templateName = systemState.currentTemplate
local aircraftType = systemState.currentAircraft
if not templateName then
trigger.action.outText("错误:当前模板为空", 10)
systemState.isSpawning = false
return false
end
env.info("开始群组复制流程: " .. aircraftType .. " [" .. templateName .. "]")
-- 销毁现有活跃群组
if systemState.activeGroupName and systemState.activeGroupName ~= templateName then
local existingGroup = Group.getByName(systemState.activeGroupName)
if existingGroup and existingGroup:isExist() then
env.info("销毁现有群组: " .. systemState.activeGroupName)
local success, err = pcall(function()
existingGroup:destroy()
end)
if success then
trigger.action.outText("清理完成", 3)
else
env.warning("销毁群组时出错: " .. tostring(err))
end
end
systemState.activeGroupName = nil
systemState.isGroupAlive = false
end
-- 延迟执行
timer.scheduleFunction(function(args)
local tplName, acType = args[1], args[2]
-- 验证模板状态
if not validateAndRecoverTemplate(tplName) then
trigger.action.outText("错误:模板准备失败 - " .. tplName, 10)
systemState.isSpawning = false
return nil
end
env.info("执行MIST群组复制: " .. tplName)
-- MIST调用
local success, result = pcall(function()
return mist.respawnGroup(tplName, true)
end)
if not success then
env.error("MIST重生失败: " .. tostring(result))
trigger.action.outText("群组复制失败,5秒后重试", 10)
-- 延迟重试机制
timer.scheduleFunction(function()
if not systemState.isGroupAlive and not systemState.isSpawning then
env.info("重试群组复制")
safeCloneAndActivateGroup()
end
end, nil, timer.getTime() + 5)
systemState.isSpawning = false
return nil
end
-- 更新系统状态
systemState.activeGroupName = tplName
systemState.templateStates[tplName].lastActive = timer.getTime()
systemState.templateStates[tplName].spawnCount = (systemState.templateStates[tplName].spawnCount or 0) + 1
-- 延迟激活复制的群组
timer.scheduleFunction(function(activationArgs)
local groupName, aircraft = activationArgs[1], activationArgs[2]
local newGroup = Group.getByName(groupName)
if newGroup and newGroup:isExist() then
-- 设置群组控制器
local controller = newGroup:getController()
if controller then
controller:setOnOff(true)
-- 激活所有单元
local units = newGroup:getUnits()
if units and #units > 0 then
for i, unit in ipairs(units) do
if unit and unit:isExist() then
local unitController = unit:getController()
if unitController then
unitController:setOnOff(true)
end
end
end
end
systemState.isGroupAlive = true
systemState.isSpawning = false
trigger.action.outText("✓ " .. aircraft .. " 就绪", 10)
env.info("群组复制激活完成: " .. aircraft)
-- 记录成功状态
systemState.templateStates[groupName].isTemplateActive = true
else
env.warning("无法获取群组控制器: " .. groupName)
systemState.isSpawning = false
end
else
env.warning("延迟激活时群组不存在: " .. groupName)
trigger.action.outText("激活失败,请检查模板: " .. groupName, 10)
systemState.isSpawning = false
end
return nil
end, {tplName, acType}, timer.getTime() + 2)
return nil
end, {templateName, aircraftType}, timer.getTime() + 1)
return true
end
-- 飞机切换函数
local function switchAircraft(aircraftType)
if not aircraftOptions[aircraftType] then
trigger.action.outText("错误:无效的飞机类型: " .. (aircraftType or "nil"), 5)
return
end
if systemState.currentAircraft == aircraftType then
trigger.action.outText("已是当前飞机: " .. aircraftType, 5)
return
end
local previousAircraft = systemState.currentAircraft
local previousTemplate = systemState.currentTemplate
trigger.action.outText("切换到: " .. aircraftType, 5)
-- 更新当前选择
systemState.currentAircraft = aircraftType
systemState.currentTemplate = aircraftOptions[aircraftType]
env.info("飞机切换: " .. previousAircraft .. " → " .. aircraftType)
env.info("模板切换: " .. (previousTemplate or "nil") .. " → " .. systemState.currentTemplate)
-- 安全销毁前一个群组
if previousTemplate and previousTemplate ~= systemState.currentTemplate then
local previousGroup = Group.getByName(previousTemplate)
if previousGroup and previousGroup:isExist() then
env.info("销毁旧群组: " .. previousTemplate)
local success, err = pcall(function()
previousGroup:destroy()
end)
if success then
systemState.templateStates[previousTemplate].isTemplateActive = false
else
env.warning("销毁旧群组失败: " .. tostring(err))
end
end
end
-- 清除活跃状态
systemState.activeGroupName = nil
systemState.isGroupAlive = false
-- 延迟执行群组复制
timer.scheduleFunction(function()
safeCloneAndActivateGroup()
end, nil, timer.getTime() + 2)
end
-- 地面目标重置函数
local function resetAllGroups()
if not isMISTAvailable() then
trigger.action.outText("错误:MIST框架未加载!", 10)
return false
end
local successCount = 0
local totalCount = 0
for _, groupName in ipairs(groupsToReset) do
totalCount = totalCount + 1
-- MIST调用
local success, result = pcall(function()
return mist.respawnGroup(groupName, true)
end)
if success then
successCount = successCount + 1
env.info("地面目标重置成功: " .. groupName)
else
env.info("地面目标重置失败: " .. groupName .. ": " .. tostring(result))
end
end
trigger.action.outText("地面目标重置完成。成功重置: " .. successCount .. "/" .. totalCount ..
" 个群组", 10)
return successCount > 0
end
-- F10菜单创建函数
local function createUnifiedF10Menu()
if not missionCommands then
env.error("missionCommands API不可用")
return false
end
-- 菜单标识符
local MAIN_MENU_NAME = "服务器设置"
-- 清除可能存在的旧菜单
pcall(function()
missionCommands.removeItem(MAIN_MENU_NAME)
end)
-- 创建主菜单
local mainMenu = missionCommands.addSubMenu(MAIN_MENU_NAME)
-- PVE飞机系统子菜单
local pveMenu = missionCommands.addSubMenu("PVE飞机系统", mainMenu)
-- 飞机选择子菜单
local aircraftMenu = missionCommands.addSubMenu("选择飞机", pveMenu)
-- 为每种飞机添加选择命令
for aircraftType, templateName in pairs(aircraftOptions) do
missionCommands.addCommand(aircraftType, aircraftMenu, function()
env.info("玩家选择飞机: " .. aircraftType)
-- 添加错误处理
local success, err = pcall(function()
switchAircraft(aircraftType)
end)
if not success then
env.error("飞机选择错误: " .. tostring(err))
trigger.action.outText("飞机选择失败,请检查日志", 5)
end
end)
end
-- PVE系统功能命令
missionCommands.addCommand("系统状态", pveMenu, function()
local statusText = "=== PVE飞机系统状态 ===\n"
statusText = statusText .. "当前飞机: " .. systemState.currentAircraft .. "\n"
statusText = statusText .. "模板名称: " .. (systemState.currentTemplate or "无") .. "\n"
statusText = statusText .. "活跃群组: " .. (systemState.activeGroupName or "无") .. "\n"
statusText = statusText .. "群组状态: " .. (systemState.isGroupAlive and "存活" or "已摧毁") .. "\n"
statusText = statusText .. "生成状态: " .. (systemState.isSpawning and "进行中" or "空闲") .. "\n"
statusText = statusText .. "MIST框架: " .. (isMISTAvailable() and "可用" or "不可用")
trigger.action.outText(statusText, 15)
end)
missionCommands.addCommand("手动重生", pveMenu, function()
if not systemState.isSpawning then
trigger.action.outText("手动触发重生...", 5)
local success, err = pcall(function()
safeCloneAndActivateGroup()
end)
if not success then
env.error("手动重生错误: " .. tostring(err))
trigger.action.outText("手动重生失败", 5)
end
else
trigger.action.outText("系统繁忙,请稍候...", 5)
end
end)
-- 目标重置子菜单
local targetMenu = missionCommands.addSubMenu("目标重置", mainMenu)
-- 地面目标重置命令
missionCommands.addCommand("重置自由飞行区所有地面目标", targetMenu, function()
trigger.action.outText("开始重置地面目标...", 5)
local success, err = pcall(function()
resetAllGroups()
end)
if not success then
env.error("目标重置错误: " .. tostring(err))
trigger.action.outText("目标重置失败", 5)
end
end)
env.info("F10菜单创建成功")
return true
end
-- 死亡事件处理
world.addEventHandler({
onEvent = function(event)
if event.id == world.event.S_EVENT_DEAD then
local initiator = event.initiator
if initiator and initiator:getGroup() then
local group = initiator:getGroup()
local groupName = group:getName()
if groupName == systemState.activeGroupName then
env.info("检测到飞机死亡: " .. groupName)
systemState.isGroupAlive = false
systemState.templateStates[groupName] = systemState.templateStates[groupName] or {}
systemState.templateStates[groupName].isTemplateActive = false
-- 5秒后重生
timer.scheduleFunction(function(deadGroup)
local success, err = pcall(function()
if not systemState.isGroupAlive and not systemState.isSpawning then
env.info("触发死亡重生: " .. deadGroup)
safeCloneAndActivateGroup()
end
end)
if not success then
env.error("死亡重生错误: " .. tostring(err))
end
return nil
end, groupName, timer.getTime() + 5)
end
end
end
end
})
-- 状态监控与自动恢复
local function startStateMonitor()
timer.scheduleFunction(function()
if systemState.activeGroupName and not isGroupActive(systemState.activeGroupName) then
if systemState.isGroupAlive and not systemState.isSpawning then
env.warning("状态监控: 检测到群组丢失 - " .. systemState.activeGroupName)
systemState.isGroupAlive = false
timer.scheduleFunction(function()
local success, err = pcall(function()
safeCloneAndActivateGroup()
end)
if not success then
env.error("状态监控重生错误: " .. tostring(err))
end
end, nil, timer.getTime() + 3)
end
end
return timer.getTime() + 5
end, nil, timer.getTime() + 5)
end
-- 初始化系统
local function initializeSystem()
env.info("初始化系统...")
-- 验证所有模板
local validTemplates = 0
for aircraftType, templateName in pairs(aircraftOptions) do
if validateAndRecoverTemplate(templateName) then
env.info("✓ 模板就绪: " .. aircraftType)
validTemplates = validTemplates + 1
else
env.error("✗ 模板故障: " .. templateName)
end
end
if validTemplates == 0 then
trigger.action.outText("错误:无可用飞机模板!", 10)
return false
end
-- F10菜单
createUnifiedF10Menu()
-- 启动状态监控
startStateMonitor()
-- 初始生成
timer.scheduleFunction(function()
local success, err = pcall(function()
safeCloneAndActivateGroup()
trigger.action.outText("系统就绪 - 死亡后5秒自动重生", 10)
end)
if not success then
env.error("初始生成错误: " .. tostring(err))
trigger.action.outText("系统启动失败", 10)
end
end, nil, timer.getTime() + 5)
return true
end
-- 启动
timer.scheduleFunction(function()
local success, err = pcall(initializeSystem)
if not success then
env.error("系统初始化失败: " .. tostring(err))
trigger.action.outText("系统启动错误: " .. tostring(err), 10)
end
end, nil, timer.getTime() + 10)
env.info("系统加载完成")
