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

洱海月 无法领取银票解决方法

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

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

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

×

最近在继续兼容老版帮会城脚本时,钱庄 NPC 的“领取银票”功能连续报了几次错:

  • GetTicketTakenTimes 为空
  • GetGuildLevel 为空
  • SetBagItemParam 最后又炸成 math.ceil(nil)

这种问题很容易让人误以为是 city0_building5.lua 本身坏了,实际上核心矛盾不在业务脚本,而在当前 skynet Lua 服务端没有把老版帮会城脚本依赖的兼容层补完整。

这篇只保留最终稳定方案,适合后面直接照着落地。

一、最终结论

这次最终只需要修改两个文件:

  • /home/ubuntu/Game2/lualib/script_base.lua
  • /home/ubuntu/Game2/services/scripts/ScriptGlobal.lua

不需要修改客户端。
也不建议直接去硬改下面两个老业务脚本:

  • /home/ubuntu/Game2/services/scripts/city0_building5.lua
  • /home/ubuntu/Game2/services/scripts/obj/city/pc_guilddirector.lua

最稳的修法不是“把钱庄脚本一处一处改到能跑”,而是把老脚本依赖的底层接口一次补齐:

  1. GetTicketTakenTimes/SetTicketTakenTimes
  2. GetGuildLevel
  3. 补银票参数常量 TICKET_ITEM_PARAM_*
  4. 兼容老版 GetBagItemParam/SetBagItemParam 的类型枚举和参数顺序

这样修完以后,“领取银票”这一条链路会完整恢复,而且同类老脚本也会一起受益。

二、为什么会连续报三次不同的错

老版 C++ 时代的帮会城脚本,默认依赖的是旧接口和旧常量。

而当前 Lua 服里,钱庄脚本虽然已经落进来了,但底层兼容口并没有全部补上,所以会出现连续报错:

1. 第一层:缺少帮会每日总领取次数接口

钱庄脚本会统计:

  • 玩家自己当天领取了多少次
  • 整个帮会当天总共发出了多少张银票

其中第二项依赖的就是:

self:GetTicketTakenTimes(selfId)
self:SetTicketTakenTimes(selfId, value)

当前 Lua 服没有这两个方法,所以第一次直接报:

attempt to call a nil value (method 'GetTicketTakenTimes')

2. 第二层:缺少帮会等级接口

后续银票发放逻辑还会根据帮会等级去计算次数或额度,老脚本直接调用:

self:GetGuildLevel(selfId)

当前 Lua 服没补这层,所以第二次又报:

attempt to call a nil value (method 'GetGuildLevel')

3. 第三层:老版道具参数接口与现服不一致

银票本质上是一个带参数的道具。
老脚本写银票金额时,用的是老版调用风格:

self:SetBagItemParam(selfId, bagpos, start, type, value)

但现服原本的 Lua 写法是:

self:SetBagItemParam(selfId, bagpos, start, value, vtype)

再加上现服 ScriptGlobal.lua 里还缺了银票参数常量:

ScriptGlobal.TICKET_ITEM_PARAM_CUR_MONEY_TYPE
ScriptGlobal.TICKET_ITEM_PARAM_MAX_MONEY_TYPE
ScriptGlobal.TICKET_ITEM_PARAM_MAX_MAX_MONEY_TYPE

于是最后传进 item:set_param 的值就错位了,最终在:

v = math.ceil(v)

这里炸出:

bad argument #1 to 'ceil' (number expected, got nil)

所以这次不是一个点坏了,而是老版银票链路依赖的兼容层缺了好几块。

三、最终修改内容

1. 在 script_base.lua 里补 GetGuildLevel

把下面这个函数补进:

function script_base:GetGuildLevel(selfId)
    local guild_id = self:GetHumanGuildID(selfId)
    if guild_id == nil or guild_id <= 0 then
        return -1
    end
    local guild = skynet.call(".Guildmanager", "lua", "get_guild_by_id", guild_id)
    if guild == nil then
        return -1
    end
    return tonumber(guild.level) or 0
end

这里返回 -1 的原因很简单:老脚本很多地方本来就是拿 < 0 判断“没有帮会”或“数据无效”,所以兼容层最好保持老逻辑习惯,不要强行改成 0

2. 在 script_base.lua 里补 GetTicketTakenTimes/SetTicketTakenTimes

继续补这两个函数:
***付费内容***
这里我没有去抢数字槽位,而是直接用了:

"guild_ticket_taken_times"

原因是当前帮会参数本身就支持字符串键,这样写更稳:

  • 不会和别的老脚本数字索引冲突
  • 语义清晰
  • 后面维护时一眼能看懂这条数据是干什么的

3. 在 ScriptGlobal.lua 里补银票参数常量

把老版银票参数定义补回来:

ScriptGlobal.TICKET_ITEM_PARAM_CUR_MONEY_START  = 0
ScriptGlobal.TICKET_ITEM_PARAM_CUR_MONEY_TYPE   = 2
ScriptGlobal.TICKET_ITEM_PARAM_MAX_MONEY_START  = 4
ScriptGlobal.TICKET_ITEM_PARAM_MAX_MONEY_TYPE   = 2
ScriptGlobal.TICKET_ITEM_PARAM_MAX_MAX_MONEY_START = 8
ScriptGlobal.TICKET_ITEM_PARAM_MAX_MAX_MONEY_TYPE  = 2

这一步非常关键。
因为钱庄脚本写银票金额时直接引用这些常量,如果这里不补,后面哪怕兼容层写好了,也还是会把 nil 往下传。

4. 在 script_base.lua 里兼容老版 GetBagItemParam/SetBagItemParam

这是这次最重要的一层。

先补两个辅助函数:

local function legacy_item_param_type_name(vtype, value)
    if type(vtype) == "string" or vtype == nil then
        return vtype
    end
    local legacy_type = tonumber(vtype)
    if legacy_type == nil then
        return vtype
    end
    if legacy_type == 2 then
        return "int"
    elseif legacy_type == 1 then
        if tonumber(value) and tonumber(value) < 0 then
            return "short"
        end
        return "ushort"
    elseif legacy_type == 0 then
        if tonumber(value) and tonumber(value) < 0 then
            return "char"
        end
        return "uchar"
    end
    return vtype
end

local function is_legacy_item_param_type(vtype)
    local legacy_type = tonumber(vtype)
    return legacy_type ~= nil and legacy_type >= 0 and legacy_type <= 2 and legacy_type == math.floor(legacy_type)
end

然后把现有的 GetBagItemParam/SetBagItemParam 改成下面这样:
***付费内容***
这段兼容层解决了两个问题:

第一,兼容老版类型枚举

老脚本常用的类型码是:

  • 0 对应 char/uchar
  • 1 对应 short/ushort
  • 2 对应 int

现服 item:set_param 要的却是字符串类型名。
所以这里必须做一次映射。

第二,兼容老版参数顺序

老脚本很多地方写的是:

SetBagItemParam(sceneId, selfId, bagpos, start, type, value)

换到当前面向对象调用后,表现出来就是:

self:SetBagItemParam(selfId, bagpos, start, type, value)

也就是老版的 typevalue 跟现服顺序正好反了。
如果不在兼容层里调换,后面就会把“类型码 2”当成金额去写,把真正金额当成类型去传,最终直接把参数写崩。

四、为什么不建议直接去改钱庄脚本

这次虽然是 city0_building5.lua 报出来的,但真正依赖老接口的远不止这一个文件。

现服里其实还有不少老脚本都在沿用这种写法:

  • GetBagItemParam(..., 2)
  • SetBagItemParam(..., 2, value)

如果只改钱庄脚本,短期能过当前测试,后面别的老道具、老任务、老活动照样会继续炸。

所以最稳的方案一定是:

  • 老业务脚本尽量不动
  • 兼容层一次补齐

这样修完之后,收益不止“领取银票恢复”,而是整批老脚本的兼容性都更稳了。

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

本版积分规则

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

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

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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