薛之猫大王
2026-02-23 af74b152737e345cc59908bbceb87ff82a2f79a5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
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