传奇脚本取字符串在列表分组中的位置判定方法与循环查找完整教程

来源: 作者: 点击:
列表在脚本里常见于地图许可名单、活动分组、行会联盟、区号过滤、自动回城点等场景。取字符串在列表中的位置,本质是把一个带分隔符的字符串按段编号,返回目标字符串所在的第几个位置。脚本可以用这个序号做优先级判断、分组归属、数组下标、发放奖励。不同引擎的分隔符规则和截取命令不一样,写之前先确认当前版本命令表,GOM、GEE、Hero、Blue 四类引擎不能直接互相套用。

一、列表字符串的标准格式

最常用的是竖线分隔,例如 D001D002
D003,位置从1开始编号。也有用英文逗号分隔的写法,例如 D001,D002,D003。还有用星号、斜杠、中文字符做分隔的自定义形式。脚本里尽量全服统一一种分隔符,不要在同一段里混用竖号和逗号,否则截取时会把混用符号当成普通字符,导致位置错乱。列表开头和结尾不要留多余分隔符,尾部多余分隔符会让循环多取到一个空字符串,计数从正常序号偏移。检查方法是用GM命令把源变量输出到聊天框,肉眼看清楚首尾是否有多余空格、换行或隐藏字符。

二、引擎自带包含判断命令

GOM、GEE 有 CHECKINLIST 命令,作用是判断一个字符串是否存在于一个用竖线分隔的列表中。常见用法:

IF

CHECKINLIST D001 D001D002
D003
SAY

目标在列表中

此命令只判断在或不在,不直接返回位置编号。若业务只关心是否存在,用它先粗筛最快;若必须知道第几位,要进入循环截取。Hero、Blue 相关命令名称和参数顺序可能存在差异,部分版本参数是列表在前、目标在后。改脚本前先用小号在NPC上实际跑一次,确认返回真假的机制,再批量接入正式逻辑。

三、GETSTR 循环定位法

在 GOM、GEE 体系里最稳妥的做法是每次从列表中按位置截取一段,与目标字符串比对,匹配后记录当前轮次变量。核心命令是 GETSTR,常见格式为:

GETSTR 源字符串 分隔符 位置 保存变量

位置参数从1开始。例如:

MOV S1 D001D002
D003
GETSTR S1 | 2 S2

执行后 S2 等于 D002。要找出年卡在“月卡季卡 年卡
至尊卡”中的位置,标准写法:

MOV S1 月卡季卡 年卡
至尊卡
MOV N0 1
MOV N1 0
[@查找循环]
GETSTR S1 | N0 S2
EQUAL S2 年卡
ACT

MOV N1 N0
GOTO @查找结束
ELSEACT

INC N0 1
GOTO @查找循环
[@查找结束]

此时 N1 就是年卡所在位置,等于3。N1 初始必须赋0,找不到时 N1 保持0,后续用 LARGE N1 0 判断是否存在,避免把无效序号当成有效数据。循环还要在 N0 超过列表总段数时强制跳出,否则会陷入无意义重复。

四、用总段数控制循环次数

循环前先确认列表一共有几段,避免 N0 无限增大。最简单的测试方法是人为指定总段数,例如手动 MOV N8 4,适用于固定列表。正式脚本建议动态统计:先把列表复制到字符串变量,用替换命令把分隔符全部换成一个特殊标记,再统计标记出现次数加1得到总段数。GOM、GEE 可用 STRINGLENGTH 或 GETSTRINGLEN 取长度,用 REPLACESTR 或 StringReplace 做替换。循环判断用 SMALL N0 N8,让 N0 从1走到列表总段数后自然结束,这样万一段落被改动也不会越界。

五、空段和连续分隔符处理

当列表出现 D001||D003 这样的连续分隔符时,GETSTR 截取第二段会得到空字符串。EQUAL 空字符串找不到目标,循环继续走。若想把空段排除在有效位置之外,在比对之前先判断截取结果是否为空,为空则直接 INC N0 继续下一轮。这样输出的 N1 表示去掉空段后的有效序号。若业务要求空段也算一个位置,就按原样计数,两种逻辑全服统一,不要混用。

六、多分隔符列表统一替换

有的列表混用竖线和逗号,例如 D001|D002,D003。处理步骤是先替换再查找。用替代命令把逗号换成竖线:

REPLACESTR S1 , |

替换后源变量统一为竖线分隔,再走 GETSTR 循环。注意替换顺序,若原列表同时存在竖线,先替换逗号不会影响原有竖线。替换完成后再保存回源变量,避免循环时重复替换。部分引擎替换命令只支持单字符批量替换,若分隔符是两个字符,要分两次替换或改用空标记办法。

七、双列表优先级判断

需要判断目标字符串在哪个列表位置更靠前时,分别调用两次查找过程,把位置存入两个数字变量,再用 LARGE 或 SMALL 比较。例如:

MOV N1 目标在列表一的位置
MOV N2 目标在列表二的位置
SMALL N1 N2
ACT

SENDMSG 5 目标在列表一顺序更靠前

位置越小优先级越高。此类写法常用于活动地图按优先级进图、行会战按联盟排序、NPC按套装等级分配奖励。比较前先判断两个位置都不为0,再进入优先级分支,避免未命中字符串参与排序。

八、Hero 与 Blue 引擎差异

Hero 系列截取字符串命令通常不叫 GETSTR,常见为 GETS 或 GETSTRING,参数一般也包含源字符串、分隔符、位置、保存变量,但顺序和分隔符写法可能不同。Blue 引擎有的用 GETSTR,有的用 INSTRING,还有的用 EXTRACTSTRING,位置是否支持变量也要查命令表。部分引擎 GETSTR 的位置参数只接受常量,不接受 N 变量,此时要改用 CALC 或临时变量拼接方式实现动态定位。引擎更换后,最稳的做法是把原来一整段循环拆成单句测试:先固定截取第1个、第2个、第3个,看保存变量是否正确,再把位置改成 N 变量测试,最后接入循环。

九、找不到目标时的默认值

循环走完没有命中,N1 保持初始0。后端逻辑先判断:

IF

LARGE N1 0
ACT

SENDMSG 5 位置是 <$STR(N1)>
ELSEACT

MESSAGEBOX 目标字符串不在列表中

若业务约定未命中按末尾处理,可把 N1 赋为总段数加1再继续。但注意不要把未命中和命中末位混为一谈,否则后续奖励发放会出现双份。所有调用位置结果的脚本,先读 N1 是否为0,再执行具体业务。

十、大小写与空格影响

列表和目标字符串必须完全一致,多一个空格都不会命中。比对前先把两边的前后空格去掉。GOM、GEE 可用 TRIM 或替代命令处理空格,Hero 用 TRIMSTR 或 MOV 加 REPLACESTR 去除。GETSTR 截取出的段落也可能自带空格,先 TRIM 再 EQUAL。全半角冒号、竖线、逗号也要统一,中文符号和英文符号会被当成不同字符串。消息变量输出时如果显示有隐藏空格,用字符码查看后再替换。

十一、地图列表序号实战

场景:角色当前地图 D002,需要知道 D002 在允许进入列表 D001D002
D003 中的序号。

MOV S1 D001D002
D003
MOV S2 D002
MOV N0 1
MOV N1 0
[@定位开始]
GETSTR S1 | N0 S3
EQUAL S2 S3
ACT

MOV N1 N0
GOTO @定位结束
ELSEACT

INC N0 1
SMALL N0 5
ACT

GOTO @定位开始
[@定位结束]

若 N1 等于3,说明 D002 是列表第三段。后续可用 EQUAL N1 3 进入第三分段执行传送或发放奖励。地图列表通常定义在脚本变量或配置文本里,读取后先统一分隔符再进循环。

十二、多关键字分组实战

玩家输入型变量中可能同时包含多个关键字,先按空格或逗号拆成段落,再对每段执行查找定位。匹配到的位置用资产变量保存,最后在对话框逐行输出。循环嵌套时注意 GOTO 跳转只在当前脚本文件内有效,不要在 QFunction 和 NPC 文件之间跨文件跳,否则跳转标签会找不到。嵌套循环建议把内层查找单独抽成一个公共标签,外层循环只负责取段和调用。

十三、长列表性能优化

列表有几千段时,每段一次 GETSTR 会明显拖慢 NPC 响应。优化先做粗筛:用 CHECKINLIST 判断目标是否在列表中,不在直接返回0,不再循环。频繁查找的目标尽量放在列表靠前位置,减少平均循环轮次。长列表在登录时载入内存变量,前后端共享,避免每次触发都从文件重新读。若列表按活动变化,只在活动切换时重新加载。脚本在循环体开头加总次数上限,防止死循环把服务器拖卡。

十四、常见错误排查

位置始终返回0:先单独测试 GETSTR 取第一段、第二段,确认位置参数从1开始;再确认保存变量是字符串变量不是数字变量;最后看分隔符是否被转义成别的字符。GOM、GEE 中竖线在部分命令里可能被当成逻辑或符号,若程序自动转义,要用替换命令先换成安全占位符再截取。

结果总是返回第一位:说明 EQUAL 比对的是截取变量的残留值,没有在每轮循环重新读取 GETSTR。检查循环标签开头是否重新执行了 GETSTR,且保存变量每轮都被覆盖。

死循环:循环条件没有限定总段数,N0 又没递增。在标签首行加 INC N0 1,再用 SMALL N0 总段数 控制继续。写完后先用最大次数5验证一轮,不要直接跑大列表。

列表尾部多一个分隔符:GETSTR 最后一段为空,循环多跑一次,N1 可能被空字符串覆盖。循环内先判断截取结果是否为空,为空则直接 GOTO 结束截取,不再进入比对。

不同引擎命令不兼容:GOM、GEE 的 GETSTR 在 Hero 上不生效,必须改成 Hero 对应命令或改用脚本逻辑实现。引擎切换后逐段手工迁移,不要批量替换命令名称。

十五、通用查找函数思路

在 QuestDiary 或专用工能脚本里写一个公共定位函数,输入源列表变量、分隔符、目标字符串,输出位置变量。函数内先统一分隔符,再用 GETSTR 循环。所有泡点脚本、活动脚本、传送脚本统一调用这个函数,避免各处重复写循环。函数入口检查参数是否传满,参数缺失直接返回0。函数结尾用 DEC 或 MOV 清空临时变量,防止跨脚本污染。

十六、位置变量做数组下标

某些引擎支持用数字位置直接做数组下标,给对应位置的角色或物品发奖励。把 N1 位置值赋给数组变量后,按分组判断。数组下标只接受数字变量,如果位置保存在字符串变量里,先转换成数字再使用。取到的位置超过数组长度上限时,先用 LARGE 比较再访问,避免数组越界报错。数组下标从0还是从1开始也要按引擎定义对齐,GETSTR 位置从1开始时,数组下标可能要从0开始,这时对 N1 减1再赋给数组。

十七、发布前验证流程

新写的查找脚本用GM账号至少跑四组用例:目标在列表开头、目标在列表中间、目标在列表末尾、目标完全不在列表。四组分别输出位置值,记录是否符合预期。再跑一组空列表、一组含空段的坏列表,确认脚本不报错不卡死。最后放在测试NPC上单次触发,观察M2日志有无脚本异常。全部通过后再接入正式NPC和服务端,避免低级的截取错误影响到玩家。