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
|