edit | blame | history | raw

伪装与怀疑值系统

suspicion.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 — 换装系统

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

物编需求:怀疑值Buff

需在编辑器中创建3个Buff:

Buff Key 名称 效果 备注
buff_sus_yellow 轻微可疑 头顶黄色粒子特效 5米可见
buff_sus_orange 明显可疑 头顶橙色粒子特效 12米可见
buff_sus_red 高度可疑 头顶红色标记特效 全图可见

所有Buff设为:
- 持续时间 = -1(由代码控制移除)
- 心跳周期 = 0
- 类型 = 正面/负面均可(仅做视觉标记)