edit | blame | history | raw

玩家系统实现

player_manager.lua

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

local M = {}

-- { player_id -> { player, unit, profession, score, respawn_count, alive } }
local player_data = {}

-----------------------------------------------------------
-- 初始化所有玩家
-----------------------------------------------------------
function M.init_all_players()
    local players = y3.player_group.get_all_players()
    for _, player in ipairs(players) do
        M.create_player_unit(player)
    end
end

-----------------------------------------------------------
-- 为单个玩家创建单位
-----------------------------------------------------------
function M.create_player_unit(player)
    local spawn = M.get_random_spawn_point()
    local unit  = y3.unit.create_unit(player, CONST.PLAYER_UNIT_KEY, spawn, math.random(0, 360))

    -- 基础属性
    local prof = player:storage_get('selected_profession') or 'shadow_blade'
    local hp   = Balance.PROFESSION_HP[prof] or 100
    unit:set_attr('最大生命', hp, '基础')
    unit:set_hp(hp)
    unit:set_bar_cnt(2)           -- 物品栏2个格子
    unit:set_pkg_cnt(0)           -- 不使用背包栏

    -- 初始伪装
    local model = M.get_random_npc_model()
    unit:replace_model(model)

    -- 标签与存储
    unit:add_tag('player_controlled')
    unit:storage_set('current_model',  model)
    unit:storage_set('previous_model', model)
    unit:storage_set('suspicion', 0)
    unit:storage_set('profession', prof)
    unit:storage_set('idle_time', 0)
    unit:storage_set('kill_cd', 0)

    -- 赋予职业技能
    local abi_key = CONST.PROFESSION_ABILITY[prof]
    unit:add_ability('英雄', abi_key, 0, 1)

    -- 记录
    player_data[player:get_id()] = {
        player        = player,
        unit          = unit,
        profession    = prof,
        score         = 0,
        respawn_left  = Balance.RESPAWN_COUNT,
        alive         = true,
    }

    return unit
end

-----------------------------------------------------------
-- 玩家死亡处理
-----------------------------------------------------------
function M.on_player_killed(killer_unit, victim_unit)
    local victim_pd = M.get_data_by_unit(victim_unit)
    local killer_pd = M.get_data_by_unit(killer_unit)

    if not victim_pd then return end
    victim_pd.alive = false

    -- 积分
    if killer_pd then
        killer_pd.score = killer_pd.score + Balance.SCORE_KILL_PLAYER
    end
    victim_pd.score = victim_pd.score + Balance.SCORE_DEATH

    -- 尸体标记
    victim_unit:add_tag('corpse')
    victim_unit:set_recycle_on_remove(false)

    -- 复活判断
    local mode = require('core.mode_manager')
    if mode.can_respawn(victim_pd) then
        victim_pd.respawn_left = victim_pd.respawn_left - 1
        y3.timer.wait(Balance.RESPAWN_TIME, function()
            M.respawn(victim_pd)
        end)
    end

    -- 胜负检查
    mode.check_victory()
end

-----------------------------------------------------------
-- 复活
-----------------------------------------------------------
function M.respawn(pd)
    local spawn = M.get_random_spawn_point()
    pd.unit:reborn(spawn)
    pd.unit:set_hp(pd.unit:get_attr('最大生命'))

    -- 新外观
    local model = M.get_random_npc_model()
    pd.unit:replace_model(model)
    pd.unit:storage_set('current_model', model)
    pd.unit:storage_set('suspicion', 0)

    pd.alive = true
end

-----------------------------------------------------------
-- 积分操作
-----------------------------------------------------------
function M.add_score(player, delta)
    local pd = player_data[player:get_id()]
    if pd then
        pd.score = pd.score + delta
    end
end

-----------------------------------------------------------
-- 查询
-----------------------------------------------------------
function M.get_data_by_unit(unit)
    for _, pd in pairs(player_data) do
        if pd.unit == unit then return pd end
    end
    return nil
end

function M.get_all_player_units()
    local list = {}
    for _, pd in pairs(player_data) do
        table.insert(list, pd)
    end
    return list
end

function M.get_alive_count(camp)
    local n = 0
    for _, pd in pairs(player_data) do
        if pd.alive then
            if not camp or pd.unit:get_camp_id() == camp then
                n = n + 1
            end
        end
    end
    return n
end

function M.get_rankings()
    local list = M.get_all_player_units()
    table.sort(list, function(a, b) return a.score > b.score end)
    for i, pd in ipairs(list) do pd.rank = i end
    return list
end

-----------------------------------------------------------
-- 工具
-----------------------------------------------------------
function M.get_random_spawn_point()
    local spawns = y3.area.get_circle_areas_by_tag('player_spawn')
    local area   = spawns[math.random(#spawns)]
    return area:get_center_point()
end

function M.get_random_npc_model()
    local pool = CONST.NPC_MODEL_POOL
    return pool[math.random(#pool)]
end

return M

事件绑定(在 main.lua 中)

-- 监听单位死亡
y3.game:event('游戏-初始化', function()
    y3.game:subscribe_event('单位-死亡', function(trg, data)
        local dead   = data.dead_unit
        local killer = data.killer_unit
        if dead and dead:has_tag('player_controlled') then
            PlayerMgr.on_player_killed(killer, dead)
        end
    end)
end)

出生点配置

在Y3编辑器中:
1. 在地图上放置8个圆形区域
2. 每个区域添加标签 player_spawn
3. 代码通过 Area.get_circle_areas_by_tag('player_spawn') 获取