local CONST = require 'config.const' local Balance = require 'config.balance' local M = {} -- { player_id -> { player, unit, profession, score, respawn_left, alive, team, is_vip } } local player_data = {} -- --------------------------------------------------------- -- 初始化所有玩家 -- --------------------------------------------------------- function M.init_all_players() local players = clicli.player_group.get_all_players():pick() 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 = clicli.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_attr('移动速度', Balance.BASE_MOVE_SPEED, '基础') unit:set_bar_cnt(2) unit:set_pkg_cnt(0) -- 初始伪装:随机NPC外观 local model = M.get_random_npc_model() if model then unit:replace_model(model) end 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] if abi_key and abi_key ~= 0 then unit:add_ability('英雄', abi_key, 0, 1) end player_data[player:get_id()] = { player = player, unit = unit, profession = prof, score = 0, respawn_left = Balance.RESPAWN_COUNT, alive = true, team = nil, is_vip = false, } 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 clicli.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() if model then pd.unit:replace_model(model) pd.unit:storage_set('current_model', model) end 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_alive_count_by_team(team_name) local n = 0 for _, pd in pairs(player_data) do if pd.alive and pd.team == team_name then n = n + 1 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 = clicli.area.get_circle_areas_by_tag('player_spawn') if #spawns == 0 then return clicli.point.create(0, 0) end local area = spawns[math.random(#spawns)] return area:get_center_point() end function M.get_random_npc_model() local pool = CONST.NPC_MODEL_POOL if #pool == 0 then return nil end return pool[math.random(#pool)] end return M