Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Squamous Eventful Plugin Suggestions

未关闭
#5,722 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 3 天内回复

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
30/100
Issue 类型
功能
描述清晰度
基本清楚
活跃度
停滞
技术栈
lua
领域
devtools

调研方向

The request proposes several new Eventful hooks: projectile item removal or landing, flow creation, and queued ranged weapon actions, plus a question about projectile firer data. Start by reading Eventful's existing event definitions and the DFHack hooks that expose projectile, flow, and unit action changes. Done means agreeing on which hooks and guarantees are needed, implementing the selected events, and adding coverage for them; the issue does not name specific files or tests.

由索引模型根据 Issue 内容生成。

描述

As per the prior discord conversation here is the stuff that would really benefit me currently. This is gonna be a little scatterbrained but here goes:

  1. Something that fires when a proj_itemst is removed from world.projectiles.all. Right now, my magazine system has to, when it is "fired", set its velocity to 0 and drop it at the shooters feet, tracking it the entire time, until it lands, at which point it is deleted and a copy added to the shooter's inventory (while this is going on, a bullet is spawned from the magazine, and the newly spawned magazine has its bullet count decreased by 1). This is what that snippet of code looks like:

local function try_return(info, attempt)
    if not S.enabled then return end

    local item = df.item.find(info.item_id)
    if not item then return end

    local still_proj = false
    pcall(function() still_proj = item_is_projectile(info.item_id) end)
    -- this scans all of world.projectiles.all each call

    if still_proj then
        if attempt <= 30 then
            dfhack.timeout(1, "ticks", function() try_return(info, attempt + 1) end)
        end
        return
    end

    -- ... inventory stuff (return mag to container)
end

-- Called for every single shot:
dfhack.timeout(2, "ticks", function() try_return(ret_info, 1) end)


local function try_remove(item_id, attempt)
    if not S.enabled then return end

    local item = df.item.find(item_id)
    if not item then return end

    local still_proj = false
    pcall(function() still_proj = item_is_projectile(item_id) end)

    if still_proj then
        if attempt <= 30 then
            dfhack.timeout(1, "ticks", function() try_remove(item_id, attempt + 1) end)
        end
        return
    end

    pcall(dfhack.items.remove, item)
end

-- Called for every single shot:
dfhack.timeout(2, "ticks", function() try_remove(item.id, 1) end)

If there was something, like, say, onProjItemLanded(item_id), it could maybe look like this:


-- ammo.lua enable():
eventful.onProjItemLanded["ammo"] = function(item_id)
local info = S.pending_returns[item_id]
if not info then return end
S.pending_returns[item_id] = nil
-- ... do the inventory work directly, no polling
end

-- shotgun.lua enable():
eventful.onProjItemLanded["shotgun"] = function(item_id)
if not S.pending_removals[item_id] then return end
S.pending_removals[item_id] = nil
pcall(dfhack.items.remove, df.item.find(item_id))
end

==================================================================================

Q: is proj.firer (the unit pointer on a proj_itemst) guaranteed to be non-nil when onProjItemCheckMovement fires?

A (that i got in discord): probably not, since projectiles can also be created by things being thrown into the air by various other mechanics

o currently i have to do this to track every shot, and it happens every tick:


local function find_firer_id(bow_id)
    if bow_id < 0 then return -1 end
    for _, unit in ipairs(df.global.world.units.active) do
        if dfhack.units.isActive(unit) and not dfhack.units.isDead(unit) then
            for _, inv_item in ipairs(unit.inventory) do
                if inv_item.item.id == bow_id then
                    return unit.id
                end
            end
        end
    end
    return -1
end

But if proj.firer could be guaranteed to be set at onProjItemCheckMovement time, I can make it look like this (or even something cleaner):


local firer_unit_id = -1
pcall(function()
if projectile.firer then
firer_unit_id = projectile.firer.id
end
end)

==================================================================================

  1. Something like "onFlowCreated", firing when a flow is created on the map either via dfhack.maps.spawnFlow() or by DF mechanics. Right now I have a script that prunes excess fire so all the flamethrowers and incendiary grenades I have don't completely torch the map each time. The check looks like this:

local CHECK_INTERVAL = 50 -- ticks between scans

local function check_fire()
    if not enabled then return end
    call_tick = call_tick + 1

    local seen = {}
    for _, block in ipairs(df.global.world.map.map_blocks) do
        for _, flow in ipairs(block.flows) do
            if flow.type == df.flow_type.Fire then
                local wx  = block.map_pos.x + flow.pos.x
                local wy  = block.map_pos.y + flow.pos.y
                local wz  = block.map_pos.z
                local key = pos_key(wx, wy, wz)
                seen[key] = true
                if not fire_ages[key] then
                    fire_ages[key] = call_tick
                elseif (call_tick - fire_ages[key]) >= GRACE_CALLS then
                    flow.expanding = false
                end
            end
        end
    end
    -- ... prune stale entries

    dfhack.timeout(CHECK_INTERVAL, "ticks", check_fire)
end

But if there was something like that, I could make it look like this:


eventful.enableEvent(eventful.eventType.FLOW_CREATED, 1)
eventful.onFlowCreated["firecontrol"] = function(pos, flow_type)
if not enabled then return end
if flow_type ~= df.flow_type.Fire then return end
local key = pos_key(pos.x, pos.y, pos.z)
if not fire_ages[key] then
fire_ages[key] = call_tick
end
end

  1. Another thing I just ran into, something like onShootRangedWeapon), which would fire when a unit queues a ShootRangedWeapon action, would be huge for me. I could cut down a lot of uses of repeat-util.
主要语言
C++
星标
2.1k
派生
509
平均合并
2 天 19 小时
30 天内合并 PR
25

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

DFHack/dfhack 的其他 Issue

查看 DFHack/dfhack 的全部 Issue

相似的 Issue

更多 C++ Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。