生活日常

DCS自动重置和手动重置地面目标的Lua脚本

久流
2026年04月13日 0 评论
DCSLua

该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("系统加载完成")

评论 (0)