edit | blame | history | raw

游戏模式实现

mode_manager.lua

local CONST   = require 'config.const'
local Balance = require 'config.balance'

local M = {}

local current_mode = 'ffa'  -- 'ffa' | 'team' | 'vip_escort'

-----------------------------------------------------------
-- 初始化
-----------------------------------------------------------
function M.init()
    current_mode = CONST.GAME_MODE  -- 从配置读取
    if current_mode == 'ffa' then
        M.init_ffa()
    elseif current_mode == 'team' then
        M.init_team()
    elseif current_mode == 'vip_escort' then
        M.init_vip()
    end
end

-----------------------------------------------------------
-- 独狼模式
-----------------------------------------------------------
function M.init_ffa()
    -- 所有玩家互为敌人(不同阵营)
    -- Y3中每个玩家默认自己一个阵营即可
end

-----------------------------------------------------------
-- 组队模式
-----------------------------------------------------------
function M.init_team()
    local PlayerMgr = require 'core.player_manager'
    local all = PlayerMgr.get_all_player_units()

    -- 按顺序分两队
    local half = math.ceil(#all / 2)
    for i, pd in ipairs(all) do
        if i <= half then
            pd.team = 'red'
            pd.unit:change_owner(CONST.TEAM_RED_PLAYER)
        else
            pd.team = 'blue'
            pd.unit:change_owner(CONST.TEAM_BLUE_PLAYER)
        end
    end

    -- 同队不可互相攻击(Y3阵营设置)
    -- 在编辑器campinfo.json中配置阵营关系为"友好"
end

-----------------------------------------------------------
-- VIP护送模式
-----------------------------------------------------------
function M.init_vip()
    local PlayerMgr = require 'core.player_manager'
    local all = PlayerMgr.get_all_player_units()

    -- 随机选VIP
    local vip_idx = math.random(#all)
    local vip_pd  = all[vip_idx]
    vip_pd.is_vip = true
    vip_pd.team   = 'escort'

    -- VIP属性
    vip_pd.unit:set_attr('最大生命', 200, '基础')
    vip_pd.unit:set_hp(200)
    vip_pd.unit:add_attr('移动速度', -0.3, '增益')
    vip_pd.unit:add_tag('vip')

    -- 分队
    local escort_count = 0
    for i, pd in ipairs(all) do
        if pd == vip_pd then goto continue end
        if escort_count < math.floor((#all - 1) / 2) then
            pd.team = 'escort'
            escort_count = escort_count + 1
        else
            pd.team = 'assassin'
        end
        ::continue::
    end

    -- 生成假VIP
    M.spawn_fake_vips(vip_pd.unit:storage_get('current_model'))

    -- 初始化撤退路线检查点
    M.init_checkpoints()
end

function M.spawn_fake_vips(vip_model)
    local fake_spawns = y3.area.get_circle_areas_by_tag('fake_vip_spawn')
    for _, area in ipairs(fake_spawns) do
        local pos = area:get_center_point()
        local fake = y3.unit.create_unit(CONST.NPC_PLAYER, CONST.NPC_UNIT_KEYS.civilian, pos, math.random(360))
        fake:replace_model(vip_model)
        fake:add_tag('npc')
        fake:add_tag('fake_vip')

        local road = CONST.FAKE_VIP_ROADS[math.random(#CONST.FAKE_VIP_ROADS)]
        fake:move_along_road(road, 1, false, true, true)
    end
end

function M.init_checkpoints()
    local cps = y3.area.get_circle_areas_by_tag('checkpoint')
    -- 按顺序排列(编辑器中通过KV标记序号)
    table.sort(cps, function(a, b)
        return (a:kv_load('order', 'integer') or 0) < (b:kv_load('order', 'integer') or 0)
    end)

    for i, cp in ipairs(cps) do
        cp:event('区域-进入', function(trg, data)
            local enter_unit = data.unit
            if enter_unit and enter_unit:has_tag('vip') then
                M.on_vip_checkpoint(i)
            end
        end)
    end

    -- 撤离点
    local exits = y3.area.get_circle_areas_by_tag('exit_point')
    for _, ex in ipairs(exits) do
        ex:event('区域-进入', function(trg, data)
            local enter_unit = data.unit
            if enter_unit and enter_unit:has_tag('vip') then
                M.on_vip_escaped()
            end
        end)
    end
end

function M.on_vip_checkpoint(index)
    -- 记录进度
    -- 全局通知
end

function M.on_vip_escaped()
    -- 护送队获胜
    local GameMgr = require 'core.game_manager'
    GameMgr.switch_state('ended')
end

-----------------------------------------------------------
-- 复活判断
-----------------------------------------------------------
function M.can_respawn(pd)
    if current_mode == 'ffa' then
        return Balance.FFA_CAN_RESPAWN and pd.respawn_left > 0
    elseif current_mode == 'team' then
        return pd.respawn_left > 0
    elseif current_mode == 'vip_escort' then
        if pd.is_vip then
            return pd.respawn_left > 0
        end
        return pd.respawn_left > 0
    end
    return false
end

-----------------------------------------------------------
-- 胜负检查
-----------------------------------------------------------
function M.check_victory()
    local PlayerMgr = require 'core.player_manager'
    local GameMgr   = require 'core.game_manager'

    if current_mode == 'ffa' then
        if PlayerMgr.get_alive_count() <= 1 then
            GameMgr.switch_state('ended')
        end

    elseif current_mode == 'team' then
        local red_alive  = PlayerMgr.get_alive_count_by_team('red')
        local blue_alive = PlayerMgr.get_alive_count_by_team('blue')
        if red_alive == 0 or blue_alive == 0 then
            GameMgr.switch_state('ended')
        end

    elseif current_mode == 'vip_escort' then
        -- VIP死亡且无复活 → 刺杀队胜
        local PlayerMgr = require 'core.player_manager'
        for _, pd in ipairs(PlayerMgr.get_all_player_units()) do
            if pd.is_vip and not pd.alive and pd.respawn_left <= 0 then
                GameMgr.switch_state('ended')
                return
            end
        end
    end
end

return M