edit | blame | history | raw

物品系统实现

item_spawner.lua

local CONST   = require 'config.const'
local Balance = require 'config.balance'

local M = {}

local spawn_points = {}  -- { area, current_item, respawn_timer }

-----------------------------------------------------------
-- 初始化
-----------------------------------------------------------
function M.init()
    local areas = y3.area.get_circle_areas_by_tag('item_spawn')
    for _, area in ipairs(areas) do
        local sp = {
            area = area,
            current_item = nil,
            respawn_timer = nil,
        }
        M.spawn_item(sp)
        table.insert(spawn_points, sp)
    end

    -- 监听物品拾取事件
    y3.game:subscribe_event('单位-获得物品', function(trg, data)
        local unit = data.unit
        local item = data.item
        if unit and unit:has_tag('player_controlled') then
            local Suspicion = require 'systems.suspicion'
            Suspicion.add(unit, 3)  -- 拾取物品+3怀疑值
        end
    end)
end

-----------------------------------------------------------
-- 在刷新点生成物品
-----------------------------------------------------------
function M.spawn_item(sp)
    local item_key = M.roll_item()
    local pos      = sp.area:get_center_point()

    -- 在地面创建物品实体
    local item = y3.item.create_item(item_key, pos)
    sp.current_item = item
end

-----------------------------------------------------------
-- 物品权重随机
-----------------------------------------------------------
local ITEM_POOL = {
    { key = CONST.ITEM_POISON,    weight = 15 },
    { key = CONST.ITEM_KNIFE,     weight = 10 },
    { key = CONST.ITEM_ARMOR,     weight = 15 },
    { key = CONST.ITEM_SMOKE,     weight = 15 },
    { key = CONST.ITEM_MASK,      weight = 8  },
    { key = CONST.ITEM_TRACKER,   weight = 15 },
    { key = CONST.ITEM_SILENCER,  weight = 10 },
    { key = CONST.ITEM_JAMMER,    weight = 12 },
}

function M.roll_item()
    local total = 0
    for _, e in ipairs(ITEM_POOL) do total = total + e.weight end
    local r = math.random(total)
    local acc = 0
    for _, e in ipairs(ITEM_POOL) do
        acc = acc + e.weight
        if r <= acc then return e.key end
    end
    return ITEM_POOL[1].key
end

-----------------------------------------------------------
-- 刷新点重生(物品被拾取后调用)
-----------------------------------------------------------
function M.on_item_picked(sp)
    sp.current_item = nil
    local delay = Balance.ITEM_RESPAWN_TIME
    -- 最后2分钟刷新加速
    local GameMgr = require 'core.game_manager'
    if GameMgr.get_state() == 'overtime' then
        delay = delay * 0.5
    end

    sp.respawn_timer = y3.timer.wait(delay, function()
        M.spawn_item(sp)
    end)
end

return M

物品使用逻辑

每个物品在物编中配置为"主动使用"物品,绑定一个技能。使用后由对应技能的施法事件触发。

毒针

-- 监听物品技能施法
-- 对前方3米目标造成持续伤害
local function use_poison(unit, ability)
    local facing = unit:get_facing()
    local pos    = unit:get_point()
    local rad    = math.rad(facing)
    local target_pos = y3.point.create(
        pos:get_x() + math.cos(rad) * 3,
        pos:get_y() + math.sin(rad) * 3
    )

    local area  = y3.area.create_circle_area(target_pos, 1.5)
    local units = area:get_all_unit_in_area()
    area:remove()

    for _, u in ipairs(units) do
        if u ~= unit and u:is_alive() then
            u:add_buff({
                key    = CONST.BUFF_POISON,
                source = unit,
                time   = 3.0,
                pulse  = 1.0,  -- 每秒心跳
            })
            break
        end
    end

    Suspicion.add(unit, 15)
end

Buff buff_poison:持续3秒,心跳1秒,每次心跳造成约17伤害(总计50),附带减速20%。

飞刀

local function use_knife(unit, ability)
    local target_point = ability:get_target(1)  -- 获取施法目标点

    -- 创建投射物
    y3.projectile.create({
        key       = CONST.PROJ_KNIFE,
        source    = unit,
        start     = unit:get_point(),
        target    = target_point,
        speed     = 15,
        max_range = 15,
        on_hit    = function(proj, hit_unit)
            unit:damage({
                target  = hit_unit,
                damage  = 40,
                type    = CONST.DAMAGE_TYPE_ASSASSINATE,
                no_miss = true,
            })
        end,
    })

    Suspicion.add(unit, 25)
end

护甲片

local function use_armor(unit, ability)
    unit:add_buff({
        key  = CONST.BUFF_SHIELD,
        time = 30.0,
    })
end

烟雾弹

local function use_smoke(unit, ability)
    local pos = unit:get_point()

    -- 粒子特效
    y3.particle.create_at_point(CONST.SFX_SMOKE, pos, 5.0)

    -- 创建烟雾区域
    local smoke_area = y3.area.create_circle_area(pos, 8)
    smoke_area:add_tag('smoke_zone')

    -- 5秒后消失
    y3.timer.wait(5.0, function()
        smoke_area:remove()
    end)

    Suspicion.add(unit, 20)
end

易容面具

local function use_mask(unit, ability)
    local model = require('core.player_manager').get_random_npc_model()
    unit:replace_model(model)
    unit:storage_set('current_model', model)
    Suspicion.set(unit, 0)
end

追踪粉

local function use_tracker(unit, ability)
    local area  = y3.area.create_circle_area(unit:get_point(), 8)
    local units = area:get_all_unit_in_area()
    area:remove()

    for _, u in ipairs(units) do
        if u:has_tag('player_controlled') and u ~= unit and u:is_alive() then
            u:add_buff({
                key    = CONST.BUFF_FOOTPRINT,
                source = unit,
                time   = 5.0,
                pulse  = 0.5,
            })
        end
    end

    Suspicion.add(unit, 10)
end

消声器

local function use_silencer(unit, ability)
    unit:add_buff({
        key  = CONST.BUFF_SILENCER,
        time = 30.0,
    })
end

干扰装置

local function use_jammer(unit, ability)
    local target_point = ability:get_target(1)
    local area = y3.area.create_circle_area(target_point, 10)
    local npcs = area:get_all_unit_in_area()
    area:remove()

    for _, npc in ipairs(npcs) do
        if npc:has_tag('npc') and npc:is_alive() then
            local random_point = y3.area.create_circle_area(target_point, 10):random_point()
            npc:move_to_pos(random_point)
        end
    end

    Suspicion.add(unit, 8)
end