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 = y3.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
-- 奔跑检测:移速超过NPC步行速度视为奔跑
local spd = unit:get_attr('移动速度', '实际')
if 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 = y3.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
-- 乘以倍率
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)
-- 阈值变化时才刷新Buff
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)
-- 添加新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
-- 离开红色阈值时恢复移速
if old_tier == 3 and new_tier < 3 then
unit:add_attr('移动速度', Balance.SUS_RED_SLOW, '增益')
end
end
function M.add(unit, delta)
local cur = unit:storage_get('suspicion') or 0
M.set(unit, math.max(0, math.min(100, cur + delta * multiplier)))
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
local CONST = require 'config.const'
local Balance = require 'config.balance'
local Suspicion = require 'systems.suspicion'
local M = {}
-----------------------------------------------------------
-- 开始换装
-----------------------------------------------------------
function M.start_disguise(player_unit, corpse_unit)
if not corpse_unit:has_tag('corpse') then return false end
if not player_unit:is_in_radius(corpse_unit, 2.0) then return false end
if player_unit:storage_get('is_disguising') then return false end
player_unit:storage_set('is_disguising', true)
player_unit:add_state(CONST.STATE_IMMOBILE)
player_unit:play_animation('channel', 1.0, 0, -1, false, true)
-- 换装时间:千面职业更快
local prof = player_unit:storage_get('profession')
local dur = prof == 'mimic' and Balance.DISGUISE_TIME_MIMIC or Balance.DISGUISE_TIME
y3.timer.wait(dur, function()
if not player_unit:is_alive() then
player_unit:storage_set('is_disguising', false)
return
end
-- 保存旧模型
local old_model = player_unit:storage_get('current_model')
player_unit:storage_set('previous_model', old_model)
-- 获取新模型
local new_model = corpse_unit:storage_get('model_key')
-- 替换
player_unit:replace_model(new_model)
player_unit:storage_set('current_model', new_model)
-- 清零怀疑值
Suspicion.set(player_unit, 0)
-- 恢复移动
player_unit:remove_state(CONST.STATE_IMMOBILE)
player_unit:stop_cur_animation()
player_unit:storage_set('is_disguising', false)
-- 尸体换成旧外观(留下的"证据")
corpse_unit:replace_model(old_model)
corpse_unit:storage_set('model_key', old_model)
end)
return true
end
return M
-- 玩家按互动键时(由input系统调用)
function M.try_player_interact(player_unit)
local pos = player_unit:get_point()
local bench_areas = y3.area.get_circle_areas_by_tag('interact_bench')
for _, area in ipairs(bench_areas) do
if area:is_point_in_area(pos) then
player_unit:stop()
player_unit:play_animation('sit', 1.0, 0, -1, true, false)
Suspicion.add(player_unit, -10)
player_unit:storage_set('interacting', true)
return true
end
end
-- 类似检查其他互动点类型...
return false
end
需在编辑器中创建3个Buff:
| Buff Key | 名称 | 效果 | 备注 |
|---|---|---|---|
buff_sus_yellow |
轻微可疑 | 头顶黄色粒子特效 | 5米可见 |
buff_sus_orange |
明显可疑 | 头顶橙色粒子特效 | 12米可见 |
buff_sus_red |
高度可疑 | 头顶红色标记特效 | 全图可见 |
所有Buff设为:
- 持续时间 = -1(由代码控制移除)
- 心跳周期 = 0
- 类型 = 正面/负面均可(仅做视觉标记)