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
-- 监听单位死亡
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') 获取