薛之猫大王
2026-02-22 35593fff68c76413ce82a918e56f127355bf6c55
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
local Balance = require 'config.balance'
local CONST   = require 'config.const'
 
local M = {}
 
local update_timer = nil
local multiplier   = 1.0
 
-- ---------------------------------------------------------
-- 启动 / 停止
-- ---------------------------------------------------------
function M.start()
    multiplier = 1.0
    update_timer = clicli.timer.loop(1.0, function()
        local PlayerMgr = require 'core.player_manager'
        for _, pd in ipairs(PlayerMgr.get_all_player_units()) do
            if pd.alive then
                M.update(pd.unit)
            end
        end
    end, '怀疑值更新')
end
 
function M.stop()
    if update_timer then
        update_timer:remove()
        update_timer = nil
    end
end
 
function M.set_multiplier(v)
    multiplier = v
end
 
-- ---------------------------------------------------------
-- 每秒更新单个玩家怀疑值
-- ---------------------------------------------------------
function M.update(unit)
    local sus   = unit:storage_get('suspicion') or 0
    local delta = 0
 
    -- 自然衰减
    delta = delta - 0.5
 
    -- 奔跑检测
    local spd = unit:get_attr('移动速度')
    if spd and spd > Balance.NPC_WALK_SPEED * 1.2 then
        delta = delta + 2
    end
 
    -- 静止过久
    local idle = unit:storage_get('idle_time') or 0
    if not unit:is_moving() then
        idle = idle + 1
        if idle > 5 then
            delta = delta + 1
        end
    else
        idle = 0
    end
    unit:storage_set('idle_time', idle)
 
    -- 混入人群:5米内NPC>=3时减少
    local nearby_area = clicli.area.create_circle_area(unit:get_point(), 5)
    local nearby      = nearby_area:get_all_unit_in_area()
    nearby_area:remove()
    local npc_count = 0
    for _, u in ipairs(nearby) do
        if u:has_tag('npc') and u:is_alive() then
            npc_count = npc_count + 1
        end
    end
    if npc_count >= 3 then
        delta = delta - 1
    end
 
    -- 暗区检测
    local dark_areas = clicli.area.get_circle_areas_by_tag('light_dark')
    for _, da in ipairs(dark_areas) do
        if da:is_point_in_area(unit:get_point()) then
            delta = delta - 1
            break
        end
    end
 
    -- 乘以倍率(仅对增加生效)
    if delta > 0 then
        delta = delta * multiplier
    end
 
    sus = math.max(0, math.min(100, sus + delta))
    M.set(unit, sus)
end
 
-- ---------------------------------------------------------
-- 设置怀疑值(含阈值Buff刷新)
-- ---------------------------------------------------------
function M.set(unit, value)
    local old = unit:storage_get('suspicion') or 0
    unit:storage_set('suspicion', value)
 
    local old_tier = M.get_tier(old)
    local new_tier = M.get_tier(value)
    if old_tier == new_tier then return end
 
    -- 清除旧Buff
    unit:remove_buffs_by_key(CONST.BUFF_SUS_YELLOW)
    unit:remove_buffs_by_key(CONST.BUFF_SUS_ORANGE)
    unit:remove_buffs_by_key(CONST.BUFF_SUS_RED)
 
    -- 离开红色阈值时恢复移速
    if old_tier == 3 and new_tier < 3 then
        unit:add_attr('移动速度', Balance.SUS_RED_SLOW, '增益')
    end
 
    -- 添加新Buff
    if new_tier == 1 then
        unit:add_buff({ key = CONST.BUFF_SUS_YELLOW, time = -1 })
    elseif new_tier == 2 then
        unit:add_buff({ key = CONST.BUFF_SUS_ORANGE, time = -1 })
    elseif new_tier == 3 then
        unit:add_buff({ key = CONST.BUFF_SUS_RED, time = -1 })
        unit:add_attr('移动速度', -Balance.SUS_RED_SLOW, '增益')
    end
end
 
function M.add(unit, delta)
    local cur = unit:storage_get('suspicion') or 0
    local applied = delta
    if delta > 0 then
        applied = delta * multiplier
    end
    M.set(unit, math.max(0, math.min(100, cur + applied)))
end
 
function M.get_tier(value)
    if value >= 80 then return 3 end
    if value >= 60 then return 2 end
    if value >= 30 then return 1 end
    return 0
end
 
return M