⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bbx2.6.txt

📁 BBX2.6使用教程
💻 TXT
字号:
我最近正好也做了个相关的,我把VB的程序给你参考下吧,希望对你有帮助,就是用VB的MSCOMM来控制的,注释我都写上了,你应该能看懂,根据你自己的需要改下就可以了,我调试过的,没问题 

MSCOMM1.COMMPORT1=1 '设置端口号为1 
MSCOMM1.SETTINGS="19200,N,8,1" '设置波特率等通信协议 
MSCOMM1.INPUTLEN=6 '设置一次从串口读取6个字节 
MSCOMM1.PORTOPEN=TRUE '打开串行口 
MSCOMM1.INPUTMODE=COMINPUTMODEBINARY '从串行口读取二进制数据 
MSCOMM1.OUTPUT=SENDDAT '发送数据 
DO UNTIL MSCOMM1.INBUFFERCOUNT>=6 '查询方式,等待收到6个字节 
DOEVENTS 
LOOP 
DATTEMP=MSCOMM1.INPUT '从串口读取数据至变体变量 
RCVDAT=DATTEMP '数据送至接收二进制数组 
TXTRCV.TEXT="" 
FOR I=0 TO 5 '接收数据送至接收文本框TXTRCV显示 
TXTRCV.TEXT=TXTRCV.TEXT&RIGHT("0"&HEX(RCVDAT(I)),2) 
NEXT I 
MSCOMM1.PORTOPEN=FALSE '关闭串行口 
CMDCOMM.ENABLED=TRUE '使能CMDCOMM按钮 
END SUB

传奇3的加解密核心就两个函数,一个加密一个解密,这两个函数在做封包分析的过程中起很重要的作用: 
Function Decode(source: string): string;
Var
Source_Len,Len : integer;
Count,c1,c2 : integer;
code : array[0..7] of byte;
a1,a2 : byte;
ind : dword;
Decode_Str : string;
label L1,L2;
Begin
Result := '';
Decode_Str := '';
code[2] := ;
code[4] := ;
code[6] := ;
Len := 0;
a1 := 0;
a2 := 0;
c1 := 2;
c2 := 0;
ind := 0;
Count := 0;
Source_Len := Length(source);
while (Count < Source_Len) do
begin
if(ord(Source[Count+1]) - $3c) < 0 then
begin
Decode_Str := Decode_Str + Source[Count+1];
inc(Len);
inc(Count);
a1 := 0;
a2 := 0;
c1 := 2;
c2 := 0;
ind := 0;
Continue;
//break;
end;
a1 := ord(Source[Count+1]) - $3c;
if Len >= Source_Len then
begin
break;
end;
if (c2 + 6) < 8 then
begin
goto L2;
end;
ind := a1 and $3f;
ind := ind shr (6-c1);
Decode_Str := Decode_Str + chr(ind or a2);
Inc(Len);
c2 := 0;
if c1 >= 6 then
begin
c1 := 2;
goto L1;
end;
inc(c1,2);
L2 :a2 := a1 shl c1;
a2 := a2 and code[c1];
c2 := c2 + (8 - c1);
L1 :inc(count);
end;
SetLength(Decode_Str,Len);
Result := Decode_Str;
end; 

function Encode(source: string): string;
var
Source_Len,Len : integer;
Count,c : integer;
a1,a2 : byte;
ind : dword;
Encode_Str : string;
begin
Result := '';
Encode_Str := '';
Len := 0;
a1 := 0;
a2 := 0;
c := 0;
ind := 0;
Count := 0;
Source_Len := Length(source);
while Count < Source_Len do
begin
if Len >= $2710 then
break;
ind := ord(source[Count+1]);
ind := ind shr (c+2);
a1 := ind or a2;
a1 := a1 and $3f;
ind := ord(source[Count+1]);
ind := ind shl (8-(c+2));
ind := ind shr 2;
a2 := ind and $3f;
inc(c,2);
if c >= 6 then
begin
if Len >= $270f then
begin
Encode_Str := Encode_Str + chr(a1 + $3c);
inc(Len);
end
else
begin
Encode_Str := Encode_Str + chr(a1 + $3c);
Encode_Str := Encode_Str + chr(a2 + $3c);
Inc(Len,2);
end;
c := 0;
a2 := 0;
end
else
begin
Encode_Str := Encode_Str + chr(a1 + $3c);
Inc(Len);
end;
inc(Count);
end;
if c > 0 then
begin
Encode_Str := Encode_Str + chr(a2 + $3c);
Inc(Len);
end;
SetLength(Encode_Str,Len);
Result := Encode_Str;
end;

新地图的制做方法,还有些ACI的东西
半年多了还没有人找出加新地图的方法,我说说我以前用的方法,不过我当时自己写的程序和ACI代码被我当年一气之下全删了,所以也没有什么现成的可以用的东西,只是凭记忆写写大概的过程

先把传奇三的地图提取出来,传奇三MAP文件的格式应该很多人都知道,前几个DW是字图长和宽,后面全是一个单元一个单元的数据,每单元数据里第几位不记的了是个能不能行走的标记。全提取出来,形成一个 ACI里叫BUFFER 
大概是这么个意思
int x_len=**;
int y_len=**;
byte map_data=new byte[x_len * y_len+8]; //加8还是+4我记不太清了。DW加8 WORD 加4。自己找个解开看看就行了
map_data 前面的两个DW还是W我记不太清了。多试试吧,好象是DW 
还有一个重要的区别 ACI的地图文件里的 高低位有些是反着的。可能是ACI天生带来的,把一个DW填为10时,有时要写 10 00 00 00 有时要写成 00 00 00 10 ,这个自己多试试吧,相信很多人已经做到这一步了。 最关键的一步就是把这个 BUFFER 用ACI自己的压缩方式压缩一下,再写到文件里,这样的一个一个文件就是组成 mir3_map.fs 的部件。不是有人已经把这个文件给分解开来了么,看看分解后的一个个文件,那就是经过压缩过的。 ACI里压缩和解压缩的函数是 compress() 和 decompress 函数原型我记不太清了,好象是  buffer compress(buffer) 自己多试试吧。 
还有更简单的方式  load_map(string mir3_map_file) 可以直接把传奇三地图文件提取到ACI里,用这个函数可以让百宝箱直接使用传奇三的地图文件,我没试过,刚写的时候突然想到这个问题,有兴趣的可以试一下
对应的函数 save_map() 这个函数把已经load_map()的地图数据写到硬盘里,是压缩过的还是没有压缩过的我记不太清了

呵呵,说到这里,还有最后的一步,读写文件。这个我不知道有没有人能实现 read_file() 读二进制 read_file_ex() 读文本文件和 write_file() . 函数原型参考ANSI C。实在不行自己猜也就猜出来的,当时我也是猜出来的。

要想读写文件,必须要有255的权限,用正常的ACI是不行的。要用到另一个函数,可以越过 权限直接运行最高权限的脚本,run_script_from_server( (buffer) string) 好象是这样的,时间太久我也记不太清了

这样一路下来,应该没有什么问题了吧。至于加密的那些ZD文件,只不过是有一个文件头,用二UE 打开一看就知道了。有特殊文件头的。读入后面的数据然后 decompress() 就得到文本文件了。没有特殊文件头的,就当做明文处理。

如果是自己研究摸索出来的,拿去赚钱无可厚非,如果是看了上面我写的东西才搞出来的,那就不要拿去卖钱了,做好了拿出来共享一下吧。实在觉的亏,那就少少收一点吧。
就是这样子了,没啥好说的了,上面都说的很清楚了,有不明白的地方自己再研究吧,就不要再来问我了。

ACI是可以编译的,不管你信不信。
BBX 采用的是 C/S 模式 看到的那个只是一个界面,不过是空壳罢了。界面的东西全在 gamebbx.dl 里 函数入口我记不太清了。自己找找就行了。能在内存里看到的那些明码的ACI 全是 gamebbx.dll里带的。
百宝箱运行时 先把 artifact.dll 载入内存 这就是虚拟机的内核。 artifact.dll 监听两个端口,一个是 等待gamebbx.dll连接的。一个是TELNET 端口。注意BBX3.0之前 TELNET端口是不自动打开的。要用函数才能打开,打开后 telnet ip port 就可以连接上了。TELNET 密码是 什么我不记的了。是三个字母,好象可以在打开TELNET的时候设定密码,具体我也记不太清了 函数可能是 telnet_on(int port , string tlnet_password)  ? 我也记不太清了。 通过TELNET 界面不受权限255的限制。 还有一个函数可以打开一个控制台 可惜太久我不记的了。同样,BBX还提供了访问系统注册表的功能。还有一系列的WINDOWS下的函数 比如 msg_box 还有一个可以输入的界面。BBX2.6下打开控制界面的是 宏 win 要求255权限 一样,这个界面也不受权限影响。而且这是一个调试信息输出的界面。ACI里 所有的调试信息都是输出到这个界面的。

想起什么再来写。

在BBX 2。6版本 artifact.dll中带着两个个文件,名字我忘记了。虚拟机一运行就执行这两个个编译过的ACI脚本,这两个文件才是内核,平常所用到的函数也全在里面,用UE打开就能找到所有的函数名了。因为编译过的ACI里函数名是不加密的。这两个文件名可以在内存中找到。直接 read_file(file_name) 再write_file()就可以把这两个文件保存下来了。

总的来说 BBX是个不错的开发外挂的平台,可惜就是没有一个好的调试器,所以写代码容易,写正确的代码就难了。因为用的虚拟机,所以要想用调试的方法来破这个平台,几乎是不可能的。要想破,只能用ACI来破。

接口 
    那些什么on什么on什么的接口函数就不用说了,定时调用就是了。哈哈。ACI里也有C#的反射?可以判定变量和函数的类型等等。指针是不提供的,只可以传址。不过应该有函数指针,我也不会用
线程同步
    写ACI如果搞不好线程同步,基本上是废的。呵呵,没记错的话是用 create_event() 和 wait_event()  好象还有信号灯的函数 create_semphore()? 
网络库
    ACI里也有标准的SOCKET实现。 socket() listen()  bind() receive() send()  send_to()? 可以支持TCP 和UDP 
有兴趣可以用ACI来写外挂,除了调试的因素。呵呵。
试试这样能不能去掉试用版本的时间限制
http://bbs.bbx8.com/viewthread.php?tid=69105&extra=page%3D1 里提供的是我很久以前发的一个试用版本,因为很久不做了,所以源程序我手上也没有,当时怎么写的也是一点印象没有了。用上提供的补丁以后,试着在ACI里加载

run_script_from_server(compress("delete_thread(\"tmain2\");"));

看能不能把时间限制去掉,行不行请跟贴说明一下
不过就是能去掉时间限制,这个种方法的免验证版本也不是完美的,还是一样会有停止练功的BUG,最好自己写ACI修正一下。这个问题我是解决不了的。

发一个最简单最稳定的持续凝血离魂+阴阳法环+ 破血狂杀aci
//适合挂变态号或者不能稳定使用的情况
//持续凝血离魂  阴阳法环  破血狂杀
void my_cast_thread();
void create_my_cast();
create_my_cast();
void my_cast_thread()
{ 
   
  if(strsrch(get_status_desc(me()), "凝血离魂") < 0 && me()["magic"][get_magic_no("凝血离魂")] )
    {
       cast(me(),"凝血离魂");
    }

  if(strsrch(get_status_desc(me()), "阴阳法环") < 0 && me()["magic"][get_magic_no("阴阳法环")] )
    {
       cast(me(),"阴阳法环");
    }

  if(strsrch(get_status_desc(me()), "破血狂杀") < 0 && me()["magic"][get_magic_no("破血狂杀")] )
    {
       cast(me(),"破血狂杀");
    }
}

void create_my_cast()
{
    delete_thread("t_my_cast_thread");
    create_thread("t_my_cast_thread","my_cast_thread");
    delete_timer("tm_create_my_cast"); 
    set_timer(4, "tm_create_my_cast", "create_my_cast");
}


void on_enter_world()
{ 
  delete_timer("tm_create_my_cast");
  set_timer(4, "tm_create_my_cast", "create_my_cast");
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -