# 伪装与怀疑值系统 ## suspicion.lua — 怀疑值系统 ```lua 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 ``` --- ## disguise.lua — 换装系统 ```lua 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 ``` --- ## 互动点降低怀疑值 ```lua -- 玩家按互动键时(由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 ``` --- ## 物编需求:怀疑值Buff 需在编辑器中创建3个Buff: | Buff Key | 名称 | 效果 | 备注 | |----------|------|------|------| | `buff_sus_yellow` | 轻微可疑 | 头顶黄色粒子特效 | 5米可见 | | `buff_sus_orange` | 明显可疑 | 头顶橙色粒子特效 | 12米可见 | | `buff_sus_red` | 高度可疑 | 头顶红色标记特效 | 全图可见 | 所有Buff设为: - 持续时间 = -1(由代码控制移除) - 心跳周期 = 0 - 类型 = 正面/负面均可(仅做视觉标记)