传奇脚本CALL传统方式与新方式双格式切换教程QuestDiaryQFunction参数传递与排错

来源: 作者: 点击:
M2里#CALL调用支持传统方式和新方式两种格式,切换位置在M2参数设置、环境设置、#CALL调用设置。两种写法表面一样,都是#CALL [\\目录\文件.txt] @标签,区别在M2把脚本翻译后怎么执行。传统方式走跳转,新方式把目标段内容直接展开到当前段。配错格式会导致变量作用域、条件判断、SENDMSG顺序和递归行为都不一样。

一、传统方式执行逻辑

文件1.txt写:

[@main]
CALL [\\ASK脚本\测试调用.txt] @ASK引擎

文件2.txt写:

[@ASK引擎]
{
IF

ACT

SENDMSG 1 test
}

传统方式M2翻译后变成:

[@main]
ACT

GOTO @ASK引擎
[@ASK引擎]
IF

ACT

SENDMSG 1 test

也就是当前段遇到#CALL先跳到目标标签,目标段独立执行,执行完按脚本结构返回或继续。适合多NPC共用一段、登录/QF统一调用、条件复杂且不想把内容全复制到主段。

传统方式注意点:

CALL后面路径用中括号包裹,标签写@段名。

目标文件必须在QuestDiary或引擎约定的脚本根下,路径按所用水桶版本写单斜杠或双反斜杠,部分Hero/老Blue可用单反斜杠,GOM/GEE常用正斜杠或按M2文档来。
目标段如果带{ }新格式包裹,传统方式仍会转成GOTO结构;{ }本身不是传统必需。
传统跳转后,当前段#CALL后面的#SAY、#ACT不会和目标任务段混成一段,调试时看执行顺序更清晰。
多层级调用别写成A调B、B调A,传统GOTO容易让人绕晕,递归用变量计数限制。

二、新方式执行逻辑

同样文件1.txt:

[@main]
CALL [\\ASK脚本\测试调用.txt] @ASK引擎

文件2.txt:

[@ASK引擎]
{
IF

ACT

SENDMSG 1 test
}

新方式M2翻译后变成:

[@main]
IF

ACT

SENDMSG 1 test

也就是不跳转,把ASK引擎段里的条件、动作直接内联到@main当前位置。适合短段复用、登录一次性检查、QF里避免多层GOTO、MakeItem/MapInfo/MapEvent/MonGen等文本配置调用。

新方式注意点:

目标段写法推荐用{ }把内容包起来,部分引擎新方式解析花括号段更直接;不写{ }某些版本也能内联,但复杂#IF/#ACT/#ELSEACT容易拆错。
内联后变量、SENDMSG、GOTO、#SAY都在当前段上下文执行。原来目标段里写GOTO回主段、写BREAK、写返回主段的逻辑可能不再适用。
新方式下被调段如果含@标签再被别处GOTO,会产生标签重复或执行顺序问题;纯功能段、发奖段、判断段用新方式最稳。
新方式支持的不只是NPC脚本,DefiniensConst.txt脚本常量、MakeItem.txt打造物品、MapInfo.txt地图信息、MapEvent.txt地图事件、MonGen.txt刷怪配置都可按新方式#CALLX/新方式调用设置处理,具体命令名看M2版本,部分配置用#CALLX而不是#CALL。

三、M2切换步骤

进M2Server,参数设置、环境设置,找到#CALL调用设置或#CALL调用新格式/传统方式选项。
全服统一选一种:老版本大量NPC用GOTO、用@段返回、用传统变量传递,保留传统方式;新做版本、大量内联发奖、登录QF轻量判断,用新方式。
改完重载NPC脚本、重载QF、重载QuestDiary;如果MapInfo/MonGen/MapEvent也走新方式,改对应配置后重载地图、重载刷怪、重载事件。
小号分别测NPC点击、登录触发、QF击杀触发、MapEvent进入地图触发,确认SENDMSG数量和顺序跟预期一致。
不要部分脚本强制新方式、部分强制传统却不改写法。同一段若依赖GOTO返回,切新方式会直接内联,原GOTO可能成死标签;同一段若依赖内联变量立即生效,切传统会跳转后变量上下文看起来“没马上执行”。

四、参数传递常规做法

CALL本身大多数引擎不直接像函数传参名,传参靠临时变量。传统方式示例:

主段设值:

[@main]
IF

ACT

MOV S0 屠龙材料
MOV N0 5
CALL [\\功能\发奖.txt] @发奖

发奖段读值:

[@发奖]
IF

CHECKVAR N0 > 0
ACT

Give <STR(S0)> <N0>
SENDMSG 6 已发放<S0>共<N0>个
ELSEACT

SENDMSG 6 发奖参数异常

S0传物品名,N0传数量,P0/D0/M0按临时需求选。P0类对话框级变量关闭对话框易清,D0小退清,M0切图部分版本清,长期参数别用它们做跨NPC传递。新方式内联时同样用S0/N0,但因为在当前段展开,主段MOV后立刻#CALL,被调段直接读同一上下文,不需要担心跳转后变量被别的段改;代价是主段和多个被调段都用S0时容易互相覆盖,复杂流程分段用不同变量名。

带多个条件示例:

[@main]
IF

CHECKGOLD > 1000000
ACT

MOV S1 终极礼包
MOV N1 1
CALL [\\功能\扣费发奖.txt] @扣费发奖

ELSEACT

SENDMSG 6 金币不足

[@扣费发奖]
IF

CHECKVAR N1 > 0
ACT

TAKE 金币 1000000
Give <STR(S1)> <N1>
SENDMSG 6 扣除100万金币发放<S1>
ELSEACT

SENDMSG 6 参数错误

传统方式这段先跳扣费发奖,执行完返回主段后续;新方式这段把扣费发奖内联到#CALL位置,主段#ELSEACT不会因跳转丢失,但如果在被调段写GOTO @main会造成重复。

五、各文件调用示例

QuestDiary NPC共用:

Mir200\Envir\QuestDiary\功能\发奖.txt写:

[@公共发奖]
{
IF

CHECKVAR N0 > 0
ACT

Give <STR(S0)> <N0>
SENDMSG 6 调用公共发奖:<S0>×<N0>
}

土城NPC写:

[@main]
IF

ACT

MOV S0 绑定元宝
MOV N0 10
CALL [\\功能\发奖.txt] @公共发奖

新方式直接内联发奖;传统方式跳到发奖.txt执行后返回。

QFunction-0登录/事件调用:

[@Login]
IF

ACT

MOV S0 登录礼包
MOV N0 1
CALL [\\功能\发奖.txt] @公共发奖

新方式下登录段直接执行发奖内容;传统方式登录段GOTO到发奖段再返回登录段后续。若发奖段写BREAK,传统方式只断发奖段,新方式内联后可能断整个登录段后续,按实际M2行为测试。

QF击杀调用:

[@PlayKillMon]
IF

CHECKMCNAME 火龙神
ACT

MOV S0 火龙材料
MOV N0 3
CALL [\\功能\发奖.txt] @公共发奖

SENDMSG 6 火龙击杀后处理完成

新方式内联发奖后再执行后面SENDMSG;传统方式跳发奖段,发奖段结束返回再执行SENDMSG。若发奖段内部有条件分支、SENDMSG、GOTO,切换格式要重测顺序。

六、非NPC配置新方式

DefiniensConst.txt脚本常量:新方式可用于常量文件调用其他常量/脚本片段,具体看M2是否开启新方式#CALLX;传统方式在常量文件里少用来跳NPC段。

MakeItem.txt打造物品:若打造材料判断、特殊发奖要调用公共段,可在M2开启对应新方式调用;写法按M2文档,不要用NPC完整#IF/#SAY套到打造文本里,只放允许的判断和动作。

MapInfo.txt地图信息:地图进入、安全区、回城规则需要调用公共处理段时,新方式可减少GOTO;传统方式在地图文本里写#CALL后跳段,返回逻辑要简单。

MapEvent.txt地图事件:定时事件、进入事件调用发奖或清场段,新方式内联更直观;传统方式注意事件段被多个地图共用时变量别串。

MonGen.txt刷怪配置:部分版本新方式#CALLX可用于刷怪后挂处理段;常规刷怪不建议在MonGen直接写复杂#CALL,放到QF、Robot或地图事件更稳。

七、常见报错与修复

script error,load fail:路径或标签找不到。确认QuestDiary根下文件存在,#CALL路径与物理目录一致,目标文件有[@标签]。例如#CALL [\\功能\积分.txt] @一万分,若物理路径是QuestDiary\功能\积分.txt且标签[@一万分]存在才不报。

双反斜杠解析异常:部分配置写\\会被当转义,QFunction里会员类脚本用\\游戏功能\会员服务.txt会加载失败,改单反斜杠\游戏功能\会员服务.txt或按引擎用正斜杠/游戏功能/会员服务.txt。

标签大小写不一致:调用@MAIN、文件里写[@main],部分引擎大小写敏感,统一半角@和相同大小写。

文件编码乱码:脚本txt用ANSI,不用UTF-8带BOM;中文路径可以但机器批量迁移时容易乱,重要功能目录用英文或拼音。

新方式内联后SENDMSG重复:被调段原来写SENDMSG、主段又写SENDMSG,内联会按顺序都发。传统方式如果主段#CALL后还有#ACT,也会发;检查是否重复调用。

新方式被调段有GOTO回主段:内联后GOTO @main会在当前段形成回跳,可能死循环。被调段只做条件+动作、不写GOTO返回,最适配新方式。

传统方式变量没传过去:主段用P0/S0,被调段用不同变量名读取;统一用S0/S1/N0/N1并在主段#ACT里MOV后再#CALL。切新方式后若主段和被调段都用S0,注意先后覆盖。

Robot/QF作用域问题:Robot遍历在线玩家里#CALL公共段,传统方式对每个对象跳段可行;新方式内联也要注意HUMAN变量作用对象是当前触发角色,不要用全局变量误替个人数据。

八、选型建议

老版本移植、大量NPC、大量@段互跳、依赖GOTO返回、GM工具批量改脚本,用传统方式。
新版本重构、登录/QF轻量判断、发奖段短、地图/刷怪/常量配置希望少跳段,用新方式。
混合环境:NPC交互保留传统,登录检查和简单发奖用新方式;但不要同一功能两段一套传统一套新复制粘贴,后期改条件会漏。
公共发奖、会员判断、签到、材料合成这种纯动作段,新方式内联最省事;任务树、多分支对话、需要返回主菜单的,传统GOTO更清楚。

九、最小可跑示例

QuestDiary\公共\发奖.txt:

[@公共发奖]
{
IF

CHECKVAR N0 > 0
ACT

Give <STR(S0)> <N0>
SENDMSG 6 公共发奖:<S0>×<N0>
ELSEACT

SENDMSG 6 发奖参数错误
}

QuestDiary\NPC\礼包.txt:

[@main]
IF

ACT

MOV S0 新手礼包
MOV N0 1
CALL [\\公共\发奖.txt] @公共发奖

SENDMSG 6 NPC流程结束

M2选新方式:点击NPC先内联公共发奖,再执行SENDMSG流程结束。
M2选传统方式:点击NPC#CALL转GOTO到公共发奖,发奖段执行完返回@main继续SENDMSG流程结束。
两者都发一次礼包;若公共发奖段加BREAK,新方式可能中断@main后续SENDMSG,传统方式只中断公共发奖返回主段再继续,需按实际M2重测后决定要不要在被调段放BREAK。

改完备份Envir,M2重载脚本,用新号测NPC、用老号测登录QF、用GM刷怪物测QF击杀调用,确认传统/新方式切换后发奖数量、SENDMSG顺序、变量值都和设计一致再上正式环境。