想弄清楚脱机脚本,先把三个词分开。按键脚本靠模拟鼠标键盘,得开着游戏窗口;内存脚本读改游戏进程里的数据,同样要开客户端;脱机脚本既不模拟点击也不依赖客户端界面,程序自己连上服务器收发数据,像客户端那样把登录、走路、打怪、捡物做完。三者里脱机的门槛最高,被服务器盯得也最紧。
下面先把脱机脚本的原理和大致写法讲清楚,再回到服务端脚本的完整编写教程。
脱机脚本靠什么跑起来
脱机脚本能跑,靠的是把客户端和服务器之间的那套对话复刻出来。客户端做的事,无非是发一串特定格式的数据,告诉服务器我要登录、我要去哪个坐标、我要打哪只怪;服务器收到后执行,再把结果发回来。脱机脚本就是替客户端说这些话。
难点有三个。一是协议,服务器认的每一种动作对应一个数据包,包里有长度、命令号、参数,位置和字节顺序错一个字节就不认。二是加密,不少服务器对包做了异或、位移这类变换,握手时还会交换密钥,算法没摸对,包发出去等于石沉大海。三是状态,服务器不会一直告诉你当前多少血、在哪、背包里有什么,这些得靠解析收到的包自己维护,状态错一步,后面全乱。
动手前要备的东西
要把协议摸清,一般先抓包。用抓包工具挂到客户端进程上,把登录、选人、进图、移动、攻击这几步的数据按顺序记录下来,再逐字节比对,找出哪个字节是命令、哪几个字节是坐标。
遇到加密的包,还要借助调试工具跟一下客户端的解密过程,把算法还原出来。语言上,早期脱机多用Delphi和易语言,界面好搭;现在用C++、Python的也不少,网络库现成,处理二进制方便。
脱机脚本的逻辑长什么样
脱机脚本的核心是一个循环加一堆判断。程序每隔很短的时间看一次角色状态,满足条件就发对应的包。
拿挂机举例,大致流程是:没有目标,就按预定路线走一步再找怪;有目标,就发攻击包;血量低于设定线,就发喝药包;地面有物品,就发捡物包;背包格子快满了,就发回城包,补给完再走回来。两次动作之间要留出间隔,发得太密服务器会拒绝,也容易被记成异常。
把这套动作抽成配置,就是脱机脚本常见的形态:外头一个调度循环,里头一串可读的条件和动作,改脚本就改行为,不必动主程序。物品过滤、药品优先级、地图路径这些,通常也写在同一份配置里。
脱机这条路要付的代价
说明白一点,脱机脚本本质上属于外挂,服务端并不欢迎。它的行为特征很明显:操作间隔高度规律、走路拐点像复制、多开号的行为几乎一致。现在不少服务端已经不靠拦截进程,而是分析行为序列,把规律操作和正常玩家区分开。被盯上轻则踢下线,重则封号,还连带清机器码和IP段。
再往上是法律层面。靠脚本牟利、篡改游戏数据,可能牵扯破坏计算机信息系统那一类的责任,售卖脚本也不在安全地带。写出来练技术是一回事,拿它上号挂机是另一回事,这个区别要拎清。
回到能正式落地的部分,服务端脚本放在哪
真正做游戏内容,写的是服务端脚本,引擎自己会读、会执行,这是名正言顺的一块。服务端装好后根目录一般是MirServer,脚本和数据都集中在Mir200\Envir下面。
Market_Def放NPC脚本,QFunction-0.txt管物品使用、会员命令这类功能。MapQuest_def里的QManage.txt是登录脚本,角色每次上线都会经过它。QuestDiary放各种数据文本,像名单、积分、活动参数,脚本读写文件都往这儿找。Robot_def管定时任务,AutoRunRobot.txt定检测周期,另一个按分钟命名的文件管几点刷BOSS、发全服公告。MonItems放爆率,一个怪一份文件。MerChant.txt是服务NPC总表,MonGen.txt管刷怪,MapInfo.txt管地图跳转,AdminList.txt写管理员名字。
新增一个NPC走两步。先在Market_Def写脚本文件,文件名叫“NPC名-地图号.txt”,比如“特修使者-3.txt”就是盟重地图上的特修使者;再到MerChant.txt登记一行,顺序是脚本名、地图号、X坐标、Y坐标、显示名、外观编号等,例如 特修使者 3 330 330 特修使者 0 87 0。登记完在引擎控制台里点重新加载、所有NPC,新脚本才生效。
服务端脚本的骨架就四块
一段脚本拆开看,无非标签、跳转、条件、动作。标签用中括号加@开头,写成[@MAIN]或[@领取奖励],是逻辑入口。跳转写法是尖括号包住显示文字,斜杠后跟目标标签,比如<领取奖励/@领取奖励>,玩家点这几个字就跳过去。换行用一个反斜杠表示,分号后面是注释,引擎会忽略。
条件、动作、输出用固定关键词引导。#IF写条件,成立才往下走;#ACT是成立时的动作,一行一条;#SAY是成立时弹出的对话;#ELSESAY是不成立时弹的内容;#ELSEACT是不成立时执行的动作;BREAK结束当前段;CLOSE关对话框。默认#IF下面多个条件是并且关系,要表达满足其一用#OR。
条件命令有哪些
写在#IF下面,用来判断玩家状态。
检测物品和钱,CHECKITEM物品名 数量看背包有没有,CHECKITEMW看身上有没有装备,CHECKGOLD看金币够不够,CHECKDURAEVA看矿物这类物品的品质。
检测等级职业声望,CHECKLEVELEX 比较符 等级数注意这里要带比较符,CHECKJOB后跟Warrior、Wizard、Taoist对应战法道,CHECKCREDITPOINT测声望,CHECKRENEWLEVEL测转生次数,CHECKMEMBERLEVEL测会员等级。
检测身份和归属,ISADMIN看是不是管理员,HAVEGUILD看有没有加入行会,ISGUILDMASTER看是不是行会老大,ISCASTLEGUILD看是不是沙城成员,ISCASTLEMASTER看是不是沙城城主,CHECKOFGUILD 行会名看是不是指定行会。
检测名单,CHECKNAMELIST角色名列表.txt、CHECKGUILDLIST行会列表.txt、CHECKACCOUNTLIST帐号列表.txt、CHECKIPLIST IP列表.txt,分别看角色名、行会、帐号、IP在不在名单里。
检测状态,CHECKHUM地图名 数量看某张地图上的人数,CHECKSLAVECOUNT看宠物数量,CHECKBAGGAGE或CheckBagSize看背包满没满,CHECKCASTLEDOOR看城门状态,ONLINELONGMIN看在线时长,CHECKEXP看经验值。
变量类判断用SMALL、LARGE、EQUAL,分别是小于、大于、等于,比如SMALL N8 10成立就是变量N8小于10。CHECK [n] 数值用来测标识变量,做任务进度常用。随机用RANDOM 数值,填2就是一半概率。
动作命令有哪些
写在#ACT或#ELSEACT下面,是真正改变状态的操作。
给和收,GIVE物品名 数量发东西,金币也能直接给;TAKE物品名 数量收回。传送,MAP地图名随机落点,MAPMOVE地图名 X Y定点传送,MONCLEAR清怪,MONGENEX按坐标刷怪。提示,SENDMSG颜色 内容往聊天框发,颜色填6是常见一种;SENDCENTERMSG往屏幕中央发。
变量操作,MOV赋值,INC加,DEC减,MUL乘,DIV整除,MOD取余,PERCENT按百分比换算,SUM求和,MOVR赋一个从0到指定值的随机数。跳转和界面,GOTO直接跳段、不再弹对话;OPENWEB打开网页,做充值跳转常用。
变量是脚本的记性
变量按作用范围分组,用错数据就串了。N是个人数字临时变量,小退归零;S是个人字符临时变量;P只在当前NPC有效,对话一关就归零。有些引擎里N0到N9、S0到S9被内部占用,别拿来当普通变量用。
C是个人数字变量,下线保存,用来记玩家进度;B是个人字符串变量,同样保存,但有长度上限。G是全局数字变量,重启也保存;A是全局字符串变量,重启保存;I和U是全局但不保存的,适合当天有效的全服数据。
还有一类标识变量,用中括号包住编号,CHECK [n] 判断,SET [n] 值设置,RESET [n] 个数批量清零,记录任务做没做过、礼包领没领过最省事。显示变量值用<
𝑆
𝑇
𝑅
(
变量
)
>
,对话框里写
<
STR(变量)>,对话框里写<STR(N1)>,玩家看到的就是实际数字。要注意引擎之间有差别,比如GOM里变量分组叫GLOBAL和HUMAN,HERO里叫GVAL和HVAL,换引擎得按新规范改一遍。
写一个完整的NPC脚本
下面这段实现的是:等级不低于10级、金币不少于1000,可以领一次奖励,领过之后不能再领。
[@MAIN]
#IF
CHECKLEVELEX > 9
CHECKGOLD 1000
#SAY
你符合领取条件。
<领取奖励/@领取>
<离开/@Exit>
#ELSESAY
等级到10级、金币不少于1000再来找我。
<知道了/@Exit>
[@领取]
#IF
CHECK [100] 0
#ACT
TAKE 金币 1000
GIVE 屠龙 1
SET [100] 1
SENDMSG 6 奖励已发放。
CLOSE
#ELSEACT
SENDMSG 6 你已经领过了。
CLOSE
入口[@MAIN]先判等级和金币,两条都成立就弹出可点选项,不成立弹另一段话。玩家点领取奖励跳到[@领取],先看标识100是不是0,是0说明没领过,就扣钱、发装备、把标识设成1,发一条提示再关窗;不是0就走#ELSEACT提示已经领过。这里判断用的 [100] 和设置用的 [100] 必须是同一个编号,编号冲突会让两个不相干的功能互相影响,动手前记一下哪个号用在哪个功能上。
挂到事件上的触发脚本
脚本还能挂到各类事件上。攻击触发写[@Attack],魔法攻击[@MagicAttack],被攻击[@Struck],被魔法打[@MagicStruck],另外进图、升级、使用物品也各有入口。
要做“戴某件装备后,打怪有一半概率削掉目标两成最大血量”,思路是先判断有没有戴这件装备,再判断目标是不是怪物,然后用随机数控制概率,最后算血量减多少。
[@Attack]
#IF
CHECKITEMW 装备 1
NOT CHECKCURRTARGETRACE = 0
RANDOM 2
#ACT
MOV N1 <
𝐴
𝑇
𝑇
𝐴
𝐶
𝐾
𝑀
𝑂
𝑁
𝑆
𝑇
𝐸
𝑅
𝑀
𝐴
𝑋
𝐻
𝑃
>
𝐷
𝐼
𝑉
𝑁
1100
𝑀
𝑈
𝐿
𝑁
120
𝑀
.
𝐻
𝑈
𝑀
𝐴
𝑁
𝐻
𝑃
−
<
ATTACKMONSTER
M
AXHP>DIVN1100MULN120M.HUMANHP−<STR(N1)>
SENDMSG 6 装备效果触发,目标掉了 <$STR(N1)> 点血。
BREAK
要点有四处。CHECKITEMW判断身上装备,NOT是取反,CHECKCURRTARGETRACE用来区分目标类型。变量不支持小数,算百分比要先除再乘,不能直接乘0.2。M.HUMANHP前面的M.表示对目标操作,不带就是对自己。<$ATTACKMONSTER_MAXHP>是被攻击怪物的最大血量,这类系统变量在引擎说明书里有专表。
输入框让脚本能收玩家的话
输入框分两种,数字输入框@@InPutInteger后跟编号,内容自动存进N变量;文本输入框@@InPutString后跟编号,内容存进S变量。玩家输入不可信,要先过滤,很多引擎在列表信息里能配非法字符黑名单,脚本里再用CHECKTEXTLENGTH限制长度、CHECKTEXTLIST挡敏感词,避免有人用引号、尖括号、百分号这类字符搞破坏。
新手最容易错的地方
路径文件名错,脚本放错目录或名字多了空格、少了地图号,引擎就找不到。编码不对,存成带BOM的UTF-8容易乱码,多数情况用无BOM的编码更稳。变量编号冲突,乱用号段会让功能互相干扰。该结尾没结尾,一段执行完不加BREAK或CLOSE,引擎会接着往下读,把下一段当成这一段的一部分。改完不重载,服务端不重新加载脚本就不生效。全角标点,命令、括号、斜杠都必须是半角。循环没有出口,GOTO绕回自己又不设跳出条件,玩家一操作就卡死。
想写好按这个顺序练
先从一个最简单的NPC起手,弹一句话加两个选项。跑通之后加条件判断,比如等级够了才给东西。再引入变量,让同一个NPC记住玩家领没领过。骨架立住之后去模仿版本自带的脚本,一次只改一处,改完重载看效果,别一口气改十几行再测。最后再碰触发类和定时类,那对时机和变量的要求更高。命令表常翻,不同引擎的命令名、参数个数有出入,用一条查一条,比死记靠谱。
传奇脱机脚本怎么写与传奇脚本编写教程从原理到实战的完整详细解析
来源:
作者:
点击:

