关于三环任务里面刷怪爆率问题引发的思考
问题:明明怪物 NPC
文件 MonsterAttrExTable.txt
文件里面标注了红熊王是 110级,但为什么进副本后的怪物是 109 级,并且设置了 110 级的红熊王 100% 爆率,他不掉包。这个是什么问题呢。
正确解答:对面此系列问题,玩过游戏的朋友应该都知道,进副本场景里面的怪物等级是根据玩家平均等级自动生成的。想必大家有还有记忆当年为了刷 F5
为了卡等级,硬生生要去算一下平均等级是不是超过了。也就是说 6 个 89级的玩家,刷的包肯定是 F5
这个是怎么算出来的呢。
服务端的位置是 D:/tlbb
目录,下面所引用的位置都是基于这个目录为基础进行查找。
- 服务端脚本
Public/Data/Script/scene.lua
里面对于场景生成的怪物有明确说明
-- 副本存玩家平均级别与怪物默认级别的级别差,差值用于场景初始化时对怪物级别进行调整,此编号固定不能改
CopyScene_LevelGap = 31
·
·
·
·
function x888888_OnSceneInit( sceneId )
--场景在初始化完成后调用
local LevelGap = LuaFnGetCopySceneData_Param( sceneId, CopyScene_LevelGap )
local monstercount = GetMonsterCount( sceneId )
local monsterobjid = -1
local i
for i=0, monstercount-1 do
monsterobjid = GetMonsterObjID( sceneId, i )
SetLevel( sceneId, monsterobjid, GetLevel( sceneId, monsterobjid ) + LevelGap )
end
end
·
·
·
# 通过代码可以看出来,场景初始化的时候这个方法是用来初始化计算每个怪的等级的
- 然后再具体找到老三环的第二环脚本,当然第一环,第三环都是一样的道理。步骤是先找到
Public/Scene/suzhou_monster.ini
文件里面的
[monster28]
guid=12300431
type=303
name=花剑雨
title=总镖头
pos_x=354
pos_z=203
dir=18
script_id=1029 // 找到这个脚本ID,去 Public/Data/Script/Script.dat 里面查找对应的路径脚本
respawn_time=1000
group_id=-1
team_id=-1
base_ai=3
ai_file=0
patrol_id=-1
shop0=-1
shop1=-1
shop2=-1
shop3=-1
ReputationID=-1
level=40
·
·
·
[monster39]
guid=8477321
type=128
name=钱宏宇
title=苏州校尉
pos_x=134
pos_z=260
dir=18
script_id=1065 // 找到这个脚本ID,去 Public/Data/Script/Script.dat 里面查找对应的路径脚本
respawn_time=1000
group_id=-1
team_id=-1
base_ai=3
ai_file=0
patrol_id=-1
shop0=-1
shop1=-1
shop2=-1
shop3=-1
ReputationID=-1
level=30
·
·
·
- 分别按上面的指定
script_id
到Public/Data/Script/Script.dat
找到对应的NPC
的脚本文件分别为
001029=\obj\suzhou\osuzhou_huajianying.lua
001065=\obj\suzhou\osuzhou_qianhongyu.lua
- 打开脚本文件,找到核心代码
\obj\suzhou\osuzhou_huajianying.lua
如下
--所拥有的事件ID列表
x001029_g_EventList = { 050101, 500610 }
--**********************************
--事件列表
--**********************************
function x001029_UpdateEventList( sceneId, selfId, targetId )
BeginEvent( sceneId )
AddText( sceneId, " 本镖局承蒙黑白两道的兄弟赏脸,走镖时从未出过纰漏,来我们镖局保镖,你就尽管放心好了。" )
local i, findId
for i, findId in x001029_g_EventList do
CallScriptFunction( findId, "OnEnumerate", sceneId, selfId, targetId )
end
AddNumText( sceneId, x001029_g_ScriptId, "连环副本介绍", 11, 105 )
AddNumText( sceneId, x001029_g_ScriptId, "楼兰连环副本介绍", 11, 106 )
EndEvent( sceneId )
DispatchEventList( sceneId, selfId, targetId )
end
--**********************************
--事件交互入口
--**********************************
function x001029_OnDefaultEvent( sceneId, selfId, targetId )
x001029_UpdateEventList( sceneId, selfId, targetId )
end
--**********************************
--事件列表选中一项
--**********************************
function x001029_OnEventRequest( sceneId, selfId, targetId, eventId )
if GetNumText() == 105 then
BeginEvent( sceneId )
AddText( sceneId, "#{function_help_077}" )
EndEvent( sceneId )
DispatchEventList( sceneId, selfId, targetId )
return
elseif GetNumText() == 106 then
BeginEvent( sceneId )
AddText( sceneId, "#{XSHBZ_80917_1}" )
EndEvent( sceneId )
DispatchEventList( sceneId, selfId, targetId )
return
end
local i, findId
for i, findId in x001029_g_EventList do
if eventId == findId then
CallScriptFunction( eventId, "OnDefaultEvent", sceneId, selfId, targetId )
return
end
end
end
- 通过脚本里面的事件ID
x001029_g_EventList = { 050101, 500610 }
在Public/Data/Script/Script.dat
找到如下
;连环副本任务
050100=\event\xunhuan\boundary_between_song_and_liao.lua
050101=\event\xunhuan\bamboo_forest.lua
050102=\event\xunhuan\field_fastness.lua
- 至此已经找到具体执行副本任务的主要脚本文件了,我们先分析其中一个。
050101=\event\xunhuan\bamboo_forest.lua
从翻译的大概意思是竹林
的意思
·
·
x050101_g_DemandKillGroup = { 2, 1 } -- 1 ~ 2 号怪物对应的 GroupID 号,与 x050101_g_DemandKill 一一对应
x050101_g_BossGroup = 2 -- Boss Group ID
x050101_g_Token = 40004315 -- 令牌号
x050101_g_Mail = 40004316 -- 书信
x050101_g_NumText_Main = 1 -- 接任务的选项
x050101_g_NumText_EnterCopyScene = 2 -- 要求进入副本的选项
x050101_g_CopySceneMap = "zhulin.nav"
x050101_g_CopySceneArea = "zhulin_area.ini"
x050101_g_CopySceneMonsterIni = "zhulin_monster_%d.ini"
x050101_g_CopySceneType = FUBEN_ZHULIN -- 副本类型,定义在ScriptGlobal.lua里面
x050101_g_LimitMembers = 1 -- 可以进副本的最小队伍人数
x050101_g_LevelLimit = 30 -- 可以进入副本的最低级别
x050101_g_TickTime = 5 -- 回调脚本的时钟时间(单位:秒/次)
x050101_g_LimitTotalHoldTime = 360 -- 副本可以存活的时间(单位:次数),如果此时间到了,则任务将会失败
x050101_g_CloseTick = 6 -- 副本关闭前倒计时(单位:次数)
x050101_g_NoUserTime = 30 -- 副本中没有人后可以继续保存的时间(单位:秒)
·
·
省
略
中
间
代
码
·
·
if denominator <= 0 then
mylevel = 0
else
mylevel = numerator / denominator
end
local PlayerMaxLevel = GetHumanMaxLevelLimit()
local iniLevel
if mylevel < 10 then
iniLevel = 10
elseif mylevel < PlayerMaxLevel then
iniLevel = floor( mylevel/10 ) * 10
else
iniLevel = PlayerMaxLevel
end
local leaderguid = LuaFnObjId2Guid( sceneId, selfId )
LuaFnSetSceneLoad_Map( sceneId, x050101_g_CopySceneMap ) -- 地图是必须选取的,而且必须在Config/SceneInfo.ini里配置好
LuaFnSetCopySceneData_TeamLeader( sceneId, leaderguid )
LuaFnSetCopySceneData_NoUserCloseTime( sceneId, x050101_g_NoUserTime * 1000 )
LuaFnSetCopySceneData_Timer( sceneId, x050101_g_TickTime * 1000 )
LuaFnSetCopySceneData_Param( sceneId, 0, x050101_g_CopySceneType )-- 设置副本数据,这里将0号索引的数据设置为999,用于表示副本号999(数字自定义)
LuaFnSetCopySceneData_Param( sceneId, 1, x050101_g_ScriptId ) -- 将1号数据设置为副本场景事件脚本号
LuaFnSetCopySceneData_Param( sceneId, 2, 0 ) -- 设置定时器调用次数
LuaFnSetCopySceneData_Param( sceneId, 3, -1 ) -- 设置副本入口场景号, 初始化
LuaFnSetCopySceneData_Param( sceneId, 4, 0 ) -- 设置副本关闭标志, 0开放,1关闭
LuaFnSetCopySceneData_Param( sceneId, 5, 0 ) -- 设置离开倒计时次数
LuaFnSetCopySceneData_Param( sceneId, 6, GetTeamId( sceneId, selfId ) ) -- 保存队伍号
LuaFnSetCopySceneData_Param( sceneId, 7, 0 ) -- 杀死Boss1的数量
LuaFnSetCopySceneData_Param( sceneId, 8, 0 ) -- 杀死Boss2的数量
LuaFnSetCopySceneData_Param( sceneId, 9, 0 ) -- 杀死Boss3的数量
LuaFnSetCopySceneData_Param( sceneId, 10, 0 ) -- 杀死Boss4的数量
LuaFnSetCopySceneData_Param( sceneId, 11, 0 ) -- 杀死Boss5的数量
LuaFnSetCopySceneData_Param( sceneId, 12, 0 ) -- 是否杀死红熊王
LuaFnSetCopySceneData_Param( sceneId, 13, iniLevel / 10 ) -- 存储玩家们的级别档次
LuaFnSetCopySceneData_Param( sceneId, 14, 0 ) -- 红熊王是否已经加血
LuaFnSetSceneLoad_Area( sceneId, x050101_g_CopySceneArea )
local monsterINI = format( x050101_g_CopySceneMonsterIni, iniLevel )
LuaFnSetSceneLoad_Monster( sceneId, monsterINI )
LuaFnSetCopySceneData_Param(sceneId, CopyScene_LevelGap, mylevel - iniLevel) -- 级别差,CopyScene_LevelGap 在 scene.lua 中赋值
local bRetSceneID = LuaFnCreateCopyScene( sceneId ) -- 初始化完成后调用创建副本函数
if bRetSceneID > 0 then
x050101_NotifyFailTips( sceneId, selfId, "副本创建成功!" )
else
x050101_NotifyFailTips( sceneId, selfId, "副本数量已达上限,请稍候再试!" )
end
- 从上面的代码得知,生成怪物的等级和怪物地图都是通过玩家等级动态生成的。会根据不同的平均等级除10后向下取整得到的数据再乘以10,得到的数值就是生成怪物的地图文件。如:你队伍平均等级为89,则调用的是
Public/Scene/zhulin_monster_80.ini
的文件
[monster0]
guid=7080501
type=4127 # 这个对应 MonsterAttrExTable.txt 里面的怪物ID
name=
title=
pos_x=65.0160
pos_z=89.6286
dir=27
script_id=-1
respawn_time=-1
group_id=2
team_id=-1
base_ai=14
ai_file=128
patrol_id=-1
shop0=-1
shop1=-1
shop2=-1
shop3=-1
[monster1]
guid=7080844
type=4117 # 这个对应 MonsterAttrExTable.txt 里面的怪物ID
name=
title=
pos_x=111.0761
pos_z=85.8364
dir=27
script_id=-1
respawn_time=-1
group_id=1
team_id=-1
base_ai=14
ai_file=127
patrol_id=-1
shop0=-1
shop1=-1
shop2=-1
shop3=-1
- 以上代表的是怪物ID,但等级是由脚本生成的。这个时候如果你要设置爆率的话,就不应该是去找怪物等级,而是找到这个怪物ID,去设置这个怪物的掉包。
总结:以上逻辑适用于天龙绝大多数的副本活动,爆率都遵循这个原则。如:新三环,老三五,刷棋,刷箱子,师门任务副本,刷星,刷四绝,燕子……等,如果爆率有问题不掉包,大多情况下都是用这个逻辑进行修复和查找f#