3楼脚本仍然不够好,因为线程一运行,就无法停止
如果你取消脚本的激活状态,线程就会出错了
下面是我加了控制代码的脚本,同时演示了全局变量的定义,及其使用
全局变量(标签) 即是能全部脚本能直接读写的地址,使用前不用重新定义
脚本中,如果有新定义同名标签,会覆盖全局标签
[ENABLE]
globalalloc(DingShi_CunDang,32) //申请空间,并定义全局变量DingShi_CunDang
// 标签 (地址)取一个容易记的名字是个好习惯,阅读和检查时更方便.
// 这种定义成功后,无法更改空间大小,以及全局标签名称!
label(_code) //定义新标签(地址) 默认是仅当前脚本有效
label(flag_out)
registersymbol(flag_out) // 注册成全局标签
label(count_run)
registersymbol(count_run) // 注册成全局标签
createthread(_code) //建立新线程,运行我们的代码
DingShi_CunDang:
db 00 00 00 00 // 清0 占用 4个 byte (00)
flag_out: // = DingShi_CunDang + 4 这地址是在代码之前
db 00 00 00 00 // 清0 占用 4个 byte (00)
_code: // 实际代码存储的地址,它 = DingShi_CunDang + 8
mov eax,[flag_out]
cmp eax,0
jne _end // 其它脚本将地址 flag_out 改为非0时, 我们可以结束线程, 这是控制实现交互的代码.
mov esi,gamesvr.exe+1CD9E0 //存储人物地址的前一个地址 -4
xor edi,edi // 计数器 清0
mov ebx,edi
_loop_15: // 遍历所有人物的存储地址 共15个
inc edi // edi 增加 1
cmp edi,#16 // 比较edi的数据大小
jnl _end_loop_15 // 1-15 读取数据 , 16时,跳出循环
mov ecx,[esi+edi*4] // 按存储的序号读取人物地址
test ecx,ecx // 判断读到的人物地址是否为0
je _loop_15 // 无数据 为0
push ecx // 不为0,则是有效人物地址,保证了存档参数的正确
call gamesvr.exe+99C10 // 存档函数,此函数返回04 有一个实参
inc ebx // 自增 1
jmp _loop_15 // 跳至下一循环
_end_loop_15: // 循环结束
push #10000 // 时间
call sleep // 暂停执行一段时间
test ebx,ebx
je _code // ebx 为0时,视为没有存档操作,无登陆人物
mov [DingShi_CunDang],ebx // 记录实时在线人数,其它脚本可能有用
mov eax,count_run
inc [eax] // 存储 有效存档的次数, 自增1
// inc [count_run] 也可以
// mov ecx,[eax] ; inc ecx ; mov [eax],ecx 也可以
jmp _code
_end: //直接使用的地址,没有预先定义 label 不是个好习惯,有可能造成标签冲突(地址不正确)
ret
count_run: // 标签放这里, 表示地址在代码之后
// 存储数据的标签,建议放在代码后面,这样容易调整
db 00 00 00 00
[DISABLE]
// dealloc(DingShi_CunDang) 这是没用的,无法撤销空间了
unregistersymbol(count_run) // 撤销全局标签,撤销后其它脚本还有访问就会出错