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

洱海月 生长点刷新时间与随机增量修复教程

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

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

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

×

1. 适用范围

本文只处理两个问题:

  1. 生长点刷新时间不准
  2. 补充时间随机增量 配了但实际不生效

本次最终修复只涉及 2 个文件:

/ubuntu/Game2/lualib/typegrowpointmanager.lua
/ubuntu/Game2/lualib/growpointenginer.lua

2. 问题现象

常见表现如下:

  1. 明明配置了 种子补充的间隔时间,实际刷新节奏忽快忽慢,或者明显比配置更快
  2. 配置了 补充时间随机增量,但现场表现始终像固定间隔
  3. 生长点达到上限后恢复补刷,重新计时不稳定

3. 老 C++ 的真实语义

通过 IDA 对老 Server 分析,生长点时间逻辑的关键语义是:

  1. 读取配置时保存两个基础字段:
    • OrgInterval
    • OrgIntervalInc
  2. 初始化当前间隔:
IntervalPerSeed = OrgInterval + OrgIntervalInc * (rand() % 100) / 100;
  1. 每次 HeartBeat 真正触发一轮补刷后,再重新计算下一轮间隔:
IntervalPerSeed = OrgInterval + OrgIntervalInc * (rand() % 100) / 100;
  1. 刷新触发条件是:
CurrentElapse > IntervalPerSeed

也就是说:

  1. 随机增量不是只在加载时算一次,而是每轮补刷后都要重新算下一轮
  2. 判定符号是 >,不是 >=
  3. 计时必须严格按真实 delta 累加,不能重复累计旧时间差

4. 配置字段对应关系

生长点配置表里和本文相关的字段是:

类型    数量    每次生成数量    生成函数    种子补充的间隔时间    补充时间随机增量

例如:

613    20    20        1800000    1200000

这条配置的含义是:

  1. 基础刷新间隔 1800000 ms
  2. 每轮额外随机增加 0 ~ 1188000 ms
  3. 每次真正完成一轮补刷后,要重新随机下一次间隔

Lua 最终实现用的是:

org + math.floor(inc * (math.random(100) - 1) / 100)

它和老 C++ 的:

org + inc * (rand() % 100) / 100

语义一致,随机范围都是 0 ~ 99%


5. 第一处修改:修复刷新计时

文件:

/ubuntu/Game2/lualib/typegrowpointmanager.lua

最终代码:

function typegrowpointmanager:do_ticks()
    if not self.enable then
        return false
    end
    local utime = skynet.time() * 1000
    if self.current_count >= self.max_appera_count then
        self.start_count = false
        self.current_elapse = 0
        self.last_update_time = utime
        return false
    end
    if not self.start_count then
        self.start_count = true
        self.last_update_time = utime
        self.current_elapse = 0
        return false
    end
    self.current_elapse = self.current_elapse + utime - self.last_update_time
    self.last_update_time = utime
    if self.current_elapse > self.interval_per_seed then
        self.current_elapse = 0
        return true
    end
    return false
end

这一版修复了 4 个关键点:

  1. 满额时停止计时,并重置 start_count/current_elapse
  2. 从“满额”回到“可补刷”时,重新起一轮完整计时
  3. 每次累计后都立即更新 last_update_time
  4. 触发条件使用 >,与老 C++ 保持一致

如果缺少这一句:

self.last_update_time = utime

后面的每次 heart_beat 都会反复累计“当前时间 - 老时间”,最终导致刷新时间越来越失真。


6. 第二处修改:加载基础间隔和随机增量

文件:

/ubuntu/Game2/lualib/growpointenginer.lua

load() 里初始化每个类型时,最终代码如下:

local max_count = tonumber(setup["数量"]) or 0
local tick_count = tonumber(setup["每次生成数量"]) or 1
if tick_count < 1 then tick_count = 1 end
if max_count > 0 and tick_count > max_count then
    tick_count = max_count
end
type_of_grow_point:set_max_appera_count(max_count)
type_of_grow_point.tick_create_count = tick_count

local type_info = self:get_type_info_of_grow_point(gp_type)
if not type_info or not type_info["脚本ID"] then
    skynet.logw("GrowPoint type_info or script_id not found for type:", gp_type)
    type_of_grow_point.enable = false
else
    type_of_grow_point.script_id = type_info["脚本ID"]
    type_of_grow_point.enable = true
end

type_of_grow_point.org_interval = tonumber(setup["种子补充的间隔时间"]) or 0
type_of_grow_point.org_interval_inc = tonumber(setup["补充时间随机增量"]) or 0
type_of_grow_point.interval_per_seed = type_of_grow_point.org_interval
    + math.floor(type_of_grow_point.org_interval_inc * (math.random(100) - 1) / 100)

这里做了两件事:

  1. 把基础间隔和随机增量分别保存到:
    • org_interval
    • org_interval_inc
  2. 初始化时就按老 C++ 公式算出第一轮 interval_per_seed

如果只写成:

type_of_grow_point.interval_per_seed = setup["种子补充的间隔时间"]

补充时间随机增量 就彻底失效了。


7. 第三处修改:每轮补刷结束后重新随机下一轮时间

文件:

/ubuntu/Game2/lualib/growpointenginer.lua

最终 heart_beat() 关键代码如下:

function growpointenginer:heart_beat()
    for _, type_of_grow_point in pairs(self.type_of_growpoints) do
        if type_of_grow_point:do_ticks() then
            local tick_count = type_of_grow_point.tick_create_count or 1
            for _ = 1, tick_count do
                local r, x, y = type_of_grow_point:create_grow_point_pos()
                if not r then
                    break
                end
                if type_of_grow_point.script_id then
                    if not self:call_script_create_func(type_of_grow_point.script_id, x, y, type_of_grow_point:get_grow_point_type()) then
                        type_of_grow_point:release_grow_point_pos(x, y)
                    end
                end
            end
            if tick_count > 1 and type_of_grow_point.script_id then
                self:call_script_tick_create_finish_func(type_of_grow_point.script_id, type_of_grow_point:get_grow_point_type(), tick_count)
            end
            local org = type_of_grow_point.org_interval or 0
            local inc = type_of_grow_point.org_interval_inc or 0
            type_of_grow_point.interval_per_seed = org + math.floor(inc * (math.random(100) - 1) / 100)
        end
    end
end

这段代码的关键不是批量创建,而是最后这 3 行:

local org = type_of_grow_point.org_interval or 0
local inc = type_of_grow_point.org_interval_inc or 0
type_of_grow_point.interval_per_seed = org + math.floor(inc * (math.random(100) - 1) / 100)

意义是:

  1. 当前这一轮补刷完成后
  2. 立刻重新随机“下一轮要等多久”
  3. 和老 C++ 的 HeartBeat 行为保持一致

如果只在 load() 时算一次随机值,而不在这里重算,那么后续所有刷新都会退化成“固定间隔”。


9. 配置检查

优先找 补充时间随机增量 > 0 的场景验证,例如:

liaoxi_growpointsetup.txt

示例配置:

613    20    20        1800000    1200000

观察点:

  1. 刷新不是永远固定 1800000 ms
  2. 不同轮次之间间隔会波动
  3. 波动范围不会超过 补充时间随机增量
您需要登录后才可以回帖 登录 | register

本版积分规则

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

GMT+8, 2026-6-24 05:47 , Processed in 0.062858 second(s), 24 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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