当前位置 : 145z游戏站 | 热血传奇 | 技术教程 | 

传奇脚本输入指令@@InPutString85与S85变量完整生命周期

热度:
写脚本的时候用@@InPutString85弹个输入框,玩家敲完字点确定,后面的事情怎么走的?S85这个变量从哪来的,什么时候被赋值,什么时候清掉,多个玩家同时输入会不会串数据?搞清楚这个流程,写输入类功能的时候就不用猜了。

**指令触发的完整链路**

NPC对话框里点一个带@@InPutString85的链接,客户端立刻弹出一个系统级输入框。这个输入框是M2直接下发给客户端的,不是NPC对话框的扩展,所以它不受NPC对话层级的影响。玩家在输入框里敲完文字点确认,客户端把文字打包成数据包发回给M2。

M2收到这个数据包之后做两件事。第一件事是校验玩家当前是否真的处于"等待输入"状态,也就是是否确实点过带@@InPutString85的链接。这个校验防止有人通过封包重放来伪造输入内容。第二件事是把玩家敲进去的文字解析出来,去掉首尾空格之后存到对应的S变量里。85对应S85,数字是几就存到S几。

存完之后M2去执行一个特定的脚本段,名字叫[@CallInPutString85]。注意这个命名规则是固定的,数字必须跟指令里的一致。如果脚本里没有写这个段,输入动作完成之后玩家界面没有任何反应,看起来就像卡住了。

**S85变量的生命周期**

S85是系统级字符变量,属于全局共享类型。它不是人物私有变量,也不是临时变量,它的存储位置在M2的内存里。一个玩家输入了内容写到S85里,另一个玩家在同一时间也触发输入写到S86里,各存各的互不干扰。但同一个数字编号的S变量在同一时刻只能存一份数据,如果一个玩家刚写完S85还没来得及处理,另一个玩家的输入又把S85覆盖了,数据就丢了。

正常流程是输入完成瞬间M2就把S85的值转移到自定义变量里,比如转到S$玩家昵称里面,然后马上把S85清空。清空写法是MOVS85或者直接SETS85,括号里什么都不填。如果忘了清空,下一次别的玩家输入的时候可能会读到上一次遗留的旧数据,特别是输入框取消或者超时关闭的时候,S85保持之前的值不变。

输入超时的情况也要考虑。客户端输入框长时间不操作,M2会发一个超时指令关掉输入状态,这时候S85不会被赋值,脚本也不会跳转到回调段。所以脚本里必须有备用的返回入口,不能让玩家卡在输入状态里出不来。

**多玩家并发时的变量隔离**

有经验的GM会问:几百个玩家同时触发输入框,S85不就乱套了吗?实际情况是M2处理这些请求是顺序执行的,每个玩家的数据包到达M2之后排队处理。玩家A先到先处理,存S85跳回调段,脚本里把值取走清空变量,全程耗时几毫秒。紧接着处理玩家B的输入,这时候S85已经被清空了,玩家B的新数据写进去,全程隔离。

但有一种情况会出问题:回调段里的脚本执行时间过长。比如回调段里接了数据库读写操作,或者复杂的字符串处理,一个玩家的输入处理耗时超过一秒,后面排队的玩家就等着。这时候如果有人在等待期间又触发了同一个输入指令,就会出现嵌套,脚本逻辑就可能乱掉。解决办法是回调段只做变量转移和简单的判断,耗时操作放到后续的独立触发段里去执行。

**非法字符过滤机制**

Hero引擎里玩家输入的文字会过一道过滤规则。配置文件里写好的禁用词列表,输入内容匹配到了就触发[@IsInFilterList]段。比如行会名字里不能带侮辱性词汇,玩家输入了立刻被拦截,跳转到提示段,S85保留原值还是被清空要看引擎版本。实测大多数版本里触发了过滤之后S85会被清空,避免非法内容留在变量里被别的脚本读取。

3K引擎的过滤跳转段名字不一样,叫[@MsgFilter],功能是一样的。如果脚本里没写对应的过滤跳转段,M2检测到非法字符之后会直接丢弃输入内容,不赋值也不跳转,玩家界面没有任何反馈,像是在输入框里敲了回车之后就没有下文了。

**字符串长度限制和截断规则**

S变量能存的字符串长度有限制。Hero引擎默认上限是100个字符,3K引擎上限在64到128之间看具体版本。玩家输入的内容超出限制,M2会从尾部截断,多余的部分直接丢掉。做行会创建功能的时候,行会名字通常限制在14个字符以内,输入超长内容的时候要先做长度检测,用CHECKLEN命令查完再往下走。

中文在变量里按两个字符还是按一个字符计算,不同引擎的处理方式不同。Hero引擎按字节算,一个中文占两个字节,所以14个字符的限制只能输入7个中文字。3K引擎按字符算,14个字符能输入14个中文。写脚本的时候查一下自己引擎的计算方式,长度限制设置错了玩家输进去的内容会被莫名其妙截断。

**@@InPutString和@@InPutInteger的区别延伸**

@@InPutString85存文本到S85,@@InPutInteger85存数字到N85,两条指令共用编号池。同一个编号85,S85和N85是独立存在的变量,一个存文本一个存数字,互相不覆盖。但是同一个编号的输入框在同一时间只能触发一个,不能同时弹S85和N85两个输入框。

实际写脚本的时候建议从10以上的编号开始用,0到9的编号容易被系统内部占用。编号大了之后比如85,只要是单个玩家单次触发的场景,编号本身没有特殊含义,只要回调段的编号匹配就行。不同NPC用不同编号可以降低变量冲突的概率,比如武器升级NPC用S80到S89,行会管理NPC用S90到S99,按功能分区管理编号。

**玩家掉线或小退时变量状态**

玩家在输入过程中掉了线,M2会清理掉这个玩家挂起的输入状态,但S85如果已经被赋值了,值会保留在内存里,直到下次有人写入新的内容或者手动清理。所以每次输入处理完成之后主动清空变量是必须写的操作,别指望系统帮你清理。

小退再上线的玩家,之前存到自定义变量里的内容还在,因为自定义变量绑定角色数据存盘了。但系统S变量在玩家小退的时候不会被保留,重启M2之后所有S变量都是空字符串。这点和自定义变量不一样,系统S变量的生命周期只到M2重启或者下一次赋值之前。
[顶部]