edit | blame | history | raw
local CONST   = require 'config.const'
local Balance = require 'config.balance'

local M = {}

local current_mode = 'ffa'

-- ---------------------------------------------------------
-- 初始化
-- ---------------------------------------------------------
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.get_mode()
    return current_mode
end

-- ---------------------------------------------------------
-- 独狼模式:所有玩家互为敌人
-- ---------------------------------------------------------
function M.init_ffa()
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'
        else
            pd.team = 'blue'
        end
    end
end

-- ---------------------------------------------------------
-- VIP护送模式
-- ---------------------------------------------------------
function M.init_vip()
    local PlayerMgr = require 'core.player_manager'
    local all = PlayerMgr.get_all_player_units()
    if #all == 0 then return end

    local vip_idx = math.random(#all)
    local vip_pd  = all[vip_idx]
    vip_pd.is_vip = true
    vip_pd.team   = 'escort'

    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 _, pd in ipairs(all) do
        if pd ~= vip_pd then
            if escort_count < math.floor((#all - 1) / 2) then
                pd.team = 'escort'
                escort_count = escort_count + 1
            else
                pd.team = 'assassin'
            end
        end
    end

    M.spawn_fake_vips(vip_pd.unit:storage_get('current_model'))
    M.init_checkpoints()
end

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

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

function M.init_checkpoints()
    local cps = clicli.area.get_circle_areas_by_tag('checkpoint')
    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 = clicli.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)
    local Notify = require 'ui.notification'
    Notify.broadcast('VIP到达检查点 ' .. tostring(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
        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
        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