找回密码
 register
搜索
查看: 19|回复: 0

洱海月 帮会资金捐助总提示“已达上限”怎么修

[复制链接]
  • 打卡等级:本地老炮
  • 打卡总天数:533
  • 打卡月天数:22
  • 打卡总奖励:530
  • 最近打卡:2026-06-24 01:45:59
Waylee 发表于 2026-4-10 10:03 | 显示全部楼层 |阅读模式 | Google Chrome | Windows 10

马上注册,查看网站隐藏内容!!

您需要 登录 才可以下载或查看,没有账号?register

×

最近补帮会城市老脚本时,碰到一个很典型、也很容易让人误判的问题:

玩家点击 NPC 的“帮会资金捐助”,明明帮会现在只有几百金,却总是提示:

帮会资金已经到达上限,不需要再捐助了。

这类问题表面上看像是 city0_building5.lua 写错了,但真正的问题并不在 NPC 脚本本身,而是在 skynet Lua 服务端的帮会兼容层没有把老脚本需要的城市属性补完整。

这篇就只写最终稳定方案,把最终代码和最终思路一次说清楚。

一、先说结论

最终只需要修改一个文件:

  • \home\ubuntu\Game2\services\guild\guildmanager_core.lua

不用改客户端。
也不用去硬改 city0_building5.lua 的业务逻辑。

最终修法做了三件事:

  1. Guildmanager 中补齐老脚本需要的 attr = 16
  2. attr = 16 按当前县衙等级动态返回帮会资金上限
  3. 统一兼容字符串和数字形式的 guild_idattr

这样修完以后,老脚本里的:

self:CityGetAttr(selfId, 16)

就能正确拿到:

  • 1级县衙 10000000
  • 2级县衙 20000000
  • 3级县衙 40000000
  • 4级县衙 60000000
  • 5级县衙 80000000

二、为什么旧脚本会误判

帮会脚本里判断是否允许捐助的代码其实一直没问题:

文件:

  • \home\ubuntu\Game2\services\scripts\city0_building5.lua

关键逻辑:

local guildmoney = self:CityGetAttr(selfId, ScriptGlobal.GUILD_MONEY)
local guildmaxmoney = self:CityGetAttr(selfId, 16)
if guildmoney < guildmaxmoney then
    self:BeginUICommand()
    self:UICommand_AddInt(targetId)
    self:EndUICommand()
    self:DispatchUICommand(selfId, 19822)
else
    self:BeginEvent(self.script_id)
    self:AddText("#{BPZJ_0801014_003}")
    self:EndEvent()
    self:DispatchEventList(selfId, targetId)
end

问题在于:

  • guildmoney 用的是 attr = 7
  • guildmaxmoney 用的是 attr = 16

而当前 Lua 版服务端原来的 Guildmanager.city_get_attr 只支持:

local eType_GUILD_ATTR = {
    [0] = "ind_level",
    [1] = "agr_level",
    [2] = "com_level",
    [3] = "def_level",
    [4] = "tech_level",
    [5] = "ambi_level",
    [7] = "money",
}

也就是说,老脚本真正依赖的 16 根本没实现。
那结果就很简单了:

  • CityGetAttr(..., 16) 取不到正确值
  • NPC 直接误判成“已达上限”

三、最终代码写法

下面是最终落地的写法,直接按这个改即可。

1. 在 guildmanager_core.lua 顶部增加兼容常量和默认资金上限

local eType_GUILD_ATTR = {
    [0] = "ind_level",      --工业度0
    [1] = "agr_level",      --农业度1
    [2] = "com_level",      --商业度2
    [3] = "def_level",      --防卫度3
    [4] = "tech_level",     --科技度4
    [5] = "ambi_level",     --扩张度5
    [7] = "money",          --帮派资金7
}
local CITY_ATTR_MAX_GUILD_MONEY = 16
local CITY_MAIN_BUILDING_MAX_LEVEL = 5
local DEFAULT_GUILD_CITY_MAX_MONEY = {
    [1] = 10000000,
    [2] = 20000000,
    [3] = 40000000,
    [4] = 60000000,
    [5] = 80000000,
}

这里的意思很直接:

  • 16 这个老属性,统一定义成“帮会资金上限”
  • 如果配置读取失败,也至少有一套老服默认值兜底

2. 增加“读取帮会城市等级”的函数

***付费内容***

这个函数的设计思路是:

  • 不从 NPC 脚本里硬编码等级
  • 直接去 .Dynamicscenemanager 取当前帮会城的运行时数据
  • 优先使用县衙等级
  • 如果县衙等级没拿到,再回退城市等级
  • 最终把结果限制在 1~5

这一步非常关键,因为帮会资金上限本来就是跟县衙等级绑定的。

3. 增加“按县衙等级返回资金上限”的函数

local function get_guild_city_max_money(guild)
    local config_info = configenginer:get_config("config_info") or {}
    local guild_cfg = config_info.Guild or config_info.guild or config_info or {}
    local level = get_guild_city_level(guild)
    local key = string.format("XianYaMaxMoney_%d", math.max(0, level - 1))
    local max_money = tonumber(guild_cfg[key])
    if max_money ~= nil then
        return math.max(0, math.floor(max_money))
    end

    local fallback = tonumber(guild_cfg.XianYaMaxMoney_0)
    if fallback ~= nil then
        return math.max(0, math.floor(fallback))
    end

    return DEFAULT_GUILD_CITY_MAX_MONEY[level] or DEFAULT_GUILD_CITY_MAX_MONEY[1]
end

这里做了三层保障:

  1. 优先从 ConfigInfo.ini 读取真实配置
  2. 配置结构异常时,退回 XianYaMaxMoney_0
  3. 如果配置仍然读不到,再退回内置默认值

这样无论线上配置怎么摆,attr = 16 都不会再返回 0

4. 修改 get_guild_by_id,兼容字符串 ID

最终写法:

function guildmanager_core:get_guild_by_id(id)
    local target_id = tonumber(id)
    for _, guild in ipairs(self.guilds) do
        local guild_id = tonumber(guild.id)
        if (target_id ~= nil and guild_id == target_id) or guild.id == id then
            self:ensure_guild_custom_position_names(guild)
            return guild
        end
    end
end

这一步看起来小,实际上非常重要。

因为 skynet 控制台、旧脚本兼容层、部分转发调用里,经常会把:

  • 1

传成:

  • "1"

如果还是原来那种严格比较,明明帮会存在,也会因为类型不一致查不到,最终继续返回 0

5. 修改 city_get_attr,正式接入 attr = 16

最终写法:

function guildmanager_core:city_get_attr(guild_id, attr)
    guild_id = tonumber(guild_id) or guild_id
    attr = tonumber(attr) or attr
    local guild = self:get_guild_by_id(guild_id)
    if guild == nil then
        return 0
    end

    if attr == CITY_ATTR_MAX_GUILD_MONEY then
        return get_guild_city_max_money(guild)
    end

    local attr_key = eType_GUILD_ATTR[attr]
    if attr_key == nil then
        return 0
    end
    if attr_key == "money" then
        return get_guild_money_value(guild)
    end
    return guild[attr_key] or 0
end

这段就是整个修复的核心。

它干了两件事:

  1. 先把 guild_idattr 统一转成数字
  2. 如果 attr == 16,就走我们刚刚补的资金上限逻辑

也就是说,从这一刻开始,老脚本里所有:

CityGetAttr(..., 16)

都能拿到正确结果。

6. 顺手把 city_change_attr 也做类型兼容

最终写法:
***付费内容***

这不是本次问题的唯一关键点,但既然已经碰到“字符串参数”这个兼容坑,就顺手把修改接口也补齐,避免后续旧脚本继续踩同一个问题。

四、为什么我不建议直接改 city0_building5.lua

很多人遇到这个问题,第一反应就是在帮会脚本里直接硬写:

local guildmaxmoney = 80000000

这种写法确实能临时过关,但不稳。

原因很简单:

  • 帮会城市等级变化后,上限会跟着变
  • 别的老脚本以后如果也用 attr = 16,还会继续报错
  • 逻辑散落在脚本里,后面维护会越来越乱

所以最稳的修法一定是:

  • 保留老脚本原有写法
  • Guildmanager 兼容层把老属性补齐

这样做的好处是:

  • 一个地方修,所有旧脚本一起生效
  • 配置仍然统一走 ConfigInfo.ini
  • 后续县衙等级变化也能自动对应正确上限

五、验证方式

改完以后,先做语法检查:

luac -p /home/ubuntu/Game2/services/guild/guildmanager_core.lua

然后进 skynet 控制台,直接验证这几条:

call .Dynamicscenemanager "get_city_runtime_debug_by_guild", 1
call .Guildmanager "city_get_attr", 1, 16
call .Guildmanager "city_get_attr", 1, 7
call .Guildmanager "get_guild_by_id", 1

只要修对了,结果应该满足:

  • get_city_runtime_debug_by_guild 返回 ok:true
  • city_get_attr, 1, 16 不再是 0
  • 4级县衙通常会回 60000000
  • 5级县衙通常会回 80000000

最后再进游戏内测试:

  • 点击“帮会资金捐助”
  • 当前资金未满时,应该正常打开捐助界面
  • 只有资金真的达到上限时,才提示“已达上限”

六、这次修复的价值

这次修复本质上不是在“改一个 NPC 功能”,而是在把老帮会城脚本依赖的一个关键兼容口补完整。

修完之后,带来的收益不只是帮会捐助恢复正常,还有两点额外价值:

  • 以后凡是依赖 CityGetAttr(..., 16) 的老脚本,都能直接复用
  • Guildmanager 对字符串 ID 和数字 ID 的兼容也更稳了

如果你也在把老 C++ 时代的帮会城逻辑往 skynet Lua 里迁,这个补法是值得直接留档的。
因为它不是临时绕过去,而是真正把兼容层补到了该补的位置。

付费看帖
剩余 14% 内容需要支付 66.00 金币 后可完整阅读
支持付费阅读,激励作者创作更好的作品。
您需要登录后才可以回帖 登录 | register

本版积分规则

QQ|雪舞知识库 ( 浙ICP备15015590号-1 | 萌ICP备20232229号|浙公网安备33048102000118号 )|天天打卡

GMT+8, 2026-6-24 05:32 , Processed in 0.065466 second(s), 26 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表